HDU3746 Cyclic Nacklace KMP求循环节
HDU3746
给定一个字符串,求:在该字符串末尾最少补充多少个字符,可以使得这个字符串获得周期性。 周期性指存在一个子串,使得该字符串可以正好分解成若干个这个子串(数量要大于1)。
Input
第一行是一个整数 T ( 0<T<=100 ) 代表测试数据的组数。 之后T行每行一个字符串,由小写字母组成,字符串的长度3<=L<=100000。
Output
每组数据输出一行结果。
Sample Input
3 AAA ABCA ABCDE
Sample Output
0 2 5
本题有一个比较重要的性质:m-next[m] == 最小循环节长度
#include <bits/stdc++.h> using namespace std; int T; int m,n; int nxt[100005]; char a[100005]; void getnxt(){ int j,i; j = -1; i = 0; nxt[0] = -1; while(i < m){ while(j != -1 && a[j] != a[i]) j = nxt[j]; nxt[++i] = ++j; } } int main(){ scanf("%d",&T); while(T--){ scanf("%s",a); m = strlen(a); getnxt(); n = m - nxt[m]; if (n != m && m % n == 0) puts("0"); else printf("%d\n",n - m%n); } return 0; }
同类题目:HDU1358
#include <bits/stdc++.h> using namespace std; int n; char a[1000005]; int nxt[1000005]; void getnxt(){ int i = 0,j = -1; nxt[0] = -1; while(i < n){ while(j != -1 && a[j] != a[i]) j = nxt[j]; nxt[++i] = ++j; } } int main(){ for (int t = 1;scanf("%d",&n) && n;t++){ scanf("%s",a); getnxt(); printf("Test case #%d\n",t); for (int i = 1;i <= n;++i){ int m = i - nxt[i]; if (i % m == 0 && i != m){ printf("%d %d\n",i,i/m); } } puts(""); } return 0; }
POJ2406(注意最小循环节的长度有可能不是字符串长度的因数.....如ababa的最小循环节长度是2)
#include <cstdio> #include <iostream> #include <cstring> #include <string> using namespace std; typedef long long ll; int m,n; int nxt[1000005]; char a[1000005]; void getnxt(){ int j,i; j = -1; i = 0; nxt[0] = -1; while(i < m){ while(j != -1 && a[j] != a[i]) j = nxt[j]; nxt[++i] = ++j; } } int main(){ while(~scanf("%s",a) && a[0] != '.'){ m = strlen(a); getnxt(); n = m - nxt[m]; if (m % n == 0) printf("%d\n",m/n); else puts("1"); } return 0; }