题意:
给出一个字符串,要求在后面添加最少的字符是的新串是循环的,且至少有两个循环节。输出最少需要添加字符的个数。
分析:
假设所给字符串为p[0...l-1],其长度为l
有这样一个结论:
这个串的最小循环节为 l - next[l]
感觉自己想得不是特别透彻,所以把别人的博客贴上来吧。
里面有个小错误就是:next[i]的值应该为j-k
对于这种情况还可以这样想:
|←②→|←④→|
------------------------
------------------------
|←①→|←③→|
这是同一个字符串
其中红色代表相同的前缀和后缀
前面那段黄的(①段)等于上面对应等长的红的部分(②段),因为前缀和后缀相同,所以②段和③段相同,③段又和正上方的④段相同,以此类推。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 100000 + 10; char p[maxn]; int next[maxn]; void get_next(char* p, int l) { int k = -1, j = 0; next[0] = -1; while(j < l) { if(k == -1 || p[k] == p[j]) { k++; j++; next[j] = k; } else k = next[k]; } } int main(void) { //freopen("3746in.txt", "r", stdin); int T; scanf("%d", &T); while(T--) { memset(next, 0, sizeof(next)); scanf("%s", p); int l = strlen(p); get_next(p, l); if(next[l] == 0) { printf("%d ", l); continue; } int cir = l - next[l]; if(l % cir == 0) { puts("0"); continue; } printf("%d ", cir - (l % cir)); } return 0; }