HDU 3746 Cyclic Nacklace ( KMP求最小循环节 )
len - nextval[len]即为最小循环节长度。
#include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> using namespace std; const int MAXN = 100100; const int INF = 1 << 20; char str[MAXN]; int nextval[MAXN]; int len; void getNext( char s[], int next[] ) { int length=len; int i=0,j=-1; next[0]=-1; while(i<length) { if(j==-1||s[i]==s[j]) { ++i; ++j; next[i]=j; } else j=next[j]; } } int main() { int T; scanf( "%d", &T ); while ( T-- ) { scanf( "%s", str ); len = strlen(str); getNext( str, nextval ); int sub = len - nextval[len]; if ( sub != len && len % sub == 0 ) puts("0"); else printf( "%d ", sub - ( nextval[len]%sub ) ); } return 0; }
HDU 1358 Period
题意:若某串的前i个字符是循环串,输出i以及循环节出现的次数。
做法跟上一题差不多
#include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> using namespace std; const int MAXN = 1000010; char str[MAXN]; int nextval[MAXN]; int len; void getNext( char s[], int next[] ) { int length=len; int i=0,j=-1; next[0]=-1; while(i<length) { if(j==-1||s[i]==s[j]) { ++i; ++j; next[i]=j; } else j=next[j]; } } int main() { int cas = 0; while ( scanf( "%d", &len ), len ) { scanf( "%s", str ); getNext( str, nextval ); printf( "Test case #%d ", ++cas ); for ( int i = 1; i <= len; ++i ) { int sub = i - nextval[i]; if ( i / sub > 1 && i % sub == 0 ) { printf("%d %d ", i, i / sub ); } } puts(""); } return 0; }
POJ 2406 Power Strings(求循环串的最大循环周期)
注意这组数据:aabaabaa
显然答案是:1
#include <cstdio> #include <cstring> #include <cstdlib> const int MAXN = 1000100; char str[MAXN]; int nextval[MAXN]; int len; void getNext(char s[],int next[]) { int length=len; int i=0,j=-1; next[0]=-1; while(i<length) { if(j==-1||s[i]==s[j]) { ++i; ++j; next[i]=j; } else j=next[j]; } } int main() { while ( scanf( "%s", str ) == 1 && str[0] != '.' ) { len = strlen(str); getNext( str, nextval ); int sub = len - nextval[len]; if ( len % sub == 0 ) printf("%d ", len / sub ); else printf("1 "); } return 0; }