http://acm.hdu.edu.cn/showproblem.php?pid=3374
SKYLONG 1
KYLONGS 2
YLONGSK 3
LONGSKY 4
ONGSKYL 5
NGSKYLO 6
GSKYLON 7
题意:输出的是最小字典序的编号,最小字典序个数,最大字典序编号,最大字典序个数
求有几个这样的字符串直接Kmp求得next数组就ok了,
然后用最小表示法求出字典序最小的,用最大表示法求出字典序最大的
最大最小表示法详解
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <cstring> using namespace std; #define N 1100000 #define met(a, b) memset(a, b, sizeof(a)) const double PI = acos(-1.0); typedef long long LL; int Next[N]; char str[N], s[N]; int Min_Repre ()///最小表示法 { int i = 0, j = 1, k = 0; met (str, 0); int len = strlen (s); strcpy (str, s); strcat (str, s); while (i<len && j<len && k<len) { int t = str[ (i+k)%len ] - str[ (j+k)%len ]; if (!t) k++; else { if (t>0) i = i+k+1; else j = j+k+1; if (i==j) j++; k = 0; } } return min (i, j); } int Max_Repre ()///最大表示法 { int i = 0, j = 1, k = 0; met (str, 0); int len = strlen (s); strcpy (str, s); strcat (str, s); while (i<len && j<len && k<len) { int t = str[ (i+k)%len ] - str[ (j+k)%len ]; if (!t) k++; else { if (t<0) i = i+k+1; else j = j+k+1; if (i==j) j++; k = 0; } } return min (i, j); } int Get_Next () { int i = 0, j = -1; Next[i] = j; int len = strlen (s); while (i<len) { if (j==-1 || s[i] == s[j]) Next[++i] = ++j; else j = Next[j]; } int l = len - Next[len]; if (len % l) return 1; return len/l; } int main () { while (scanf ("%s", s) != EOF) { met (Next, 0); int ans = Get_Next (); int a1 = Min_Repre (); int a2 = Max_Repre (); printf ("%d %d %d %d\n", a1+1, ans, a2+1, ans); } return 0; }