HDU 3374 String Problem

String Problem
Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u

Description

Give you a string with length N, you can generate N strings by left shifts. For example let consider the string “SKYLONG”, we can generate seven strings: 
String Rank 
SKYLONG 1 
KYLONGS 2 
YLONGSK 3 
LONGSKY 4 
ONGSKYL 5 
NGSKYLO 6 
GSKYLON 7 
and lexicographically first of them is GSKYLON, lexicographically last is YLONGSK, both of them appear only once. 
  Your task is easy, calculate the lexicographically fisrt string’s Rank (if there are multiple answers, choose the smallest one), its times, lexicographically last string’s Rank (if there are multiple answers, choose the smallest one), and its times also. 
 

Input

  Each line contains one line the string S with length N (N <= 1000000) formed by lower case letters.
 

Output

Output four integers separated by one space, lexicographically fisrt string’s Rank (if there are multiple answers, choose the smallest one), the string’s times in the N generated strings, lexicographically last string’s Rank (if there are multiple answers, choose the smallest one), and its times also.
 

Sample Input

abcder aaaaaa ababab
 

Sample Output

1 1 6 1 1 6 1 6 1 3 2 3

题目大意:给出一个,字符串,每次将最前一个字符放到最后,知道形成一周,然后按照每个字符串出现的先后排个名次,现在要求求出字典序最小的字符串和字典序最大的字符串为RANK几。并输出它们的出现次数,如果出现次数不只一次,那么输出RANK值较小的。


解题思路:KMP中的求最小串,然后用最小串去原字符串中求匹配数量。




#include <cstring>
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
#define maxn 1111111

char P[maxn], T[maxn<<1];
int n, m;
#define next Next
int next[maxn];

void get_next (char *p) {
	int t;
	t = next[0] = -1;
	int j = 0, m = strlen (p);
	while (j < m) {
		if (t < 0 || p[j] == p[t]) {//匹配
			j++, t++;
			next[j] = t;
		}
		else //失配
			t = next[t];
	}
}

int kmp () {
	get_next (P);
	int i = 0, j = 0, ans = 0;
	while (i < n && j < m) {
		if (j < 0 || T[i] == P[j]) {
			i++, j++;
		}
		else {
			j = next[j];
		}
		if (j == m) {
            ans++;
            j = next[j];
		}
	}
	return ans;
}

int min_max_express (char *s, int len,bool flag) {
    int i=0,j=1,k=0;
    while (i<len && j<len && k<len) {
        int t = s[(j+k)%len]-s[(i+k)%len];
        if (t==0) k++;
        else {
            if (flag) {
                if (t>0) j+=k+1;
                else i+=k+1;
            }
            else {
                if (t>0) i+=k+1;
                else j+=k+1;
            }
            if (i==j) j++;
            k=0;
        }
    }
    return min(i,j);
}

int main () {
    //freopen ("in.txt", "r", stdin);
	while (scanf ("%s", P) == 1) {
        m = n = strlen (P);
        for (int i = 0; i < 2*n-1; i++) T[i] = P[i%n];
        n <<= 1; n--;
        T[n] = 0;
        int ans = kmp ();
        printf ("%d %d %d %d
", min_max_express (P, m, 1)+1, ans, min_max_express (P, m, 0)+1, ans);
	}
	return 0;
}


原文地址:https://www.cnblogs.com/zswbky/p/6717926.html