题目含义:
求最少添加几个字符使得原字符串构成一个多于一个循环节的循环
思路:
KMP的next数组记录的是后缀和前缀里面最长公共字符串,所以next[len]记录的就是整个字符串的最长公共前缀后缀,字符串的长度 len 减去next[len]就是一个循环节的长度(如果一个字符串中只有一个循环节显然成立,如果有多于一个循环节,循环节会合并成为更长的循环节,因此减去next[len]求得的就是一个循环节的长度),最后特判一下,如果next[len] = 0表示没有办法构成多于一个循环,需要添加一个和原串一模一样的字符串,如果 len % res == 0表示字符串的长度是循环节的整数倍,也就是说已经有多于一个循环了,就不需要添加了,否则的话,就计算一下 res - len % res(后面的字符差多少个能构成一个循环节)
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int nex[110000];
void get_next(char* p){
int len = strlen(p);
nex[0] = -1;
int i = 0, k = -1;
while (i < len){
if(k == -1 || p[i] == p[k]){
++i, ++k;
nex[i] = k;
}
else k = nex[k];
}
}
int main()
{
int T;
char s[100010];
scanf("%d", &T);
while (T--){
memset(nex, 0, sizeof nex);
scanf("%s", s);
get_next(s);
int len = strlen(s);
int res = len - nex[len];
if(nex[len] == 0)printf("%d\n", len);
else if(len % res == 0)puts("0");
else printf("%d\n", res - len % res);
}
return 0;
}