题意:给你一个字符串,问你至少增添几个字符可以把这个字符串变成一个循环字符串(ababa的循环节是ab,不是aba);
解题思路:利用kmp中的next数组,首先在这样求next的数组的代码里:
void get_next() { int j,k; j=0;k=-1;next1[0]=-1; while(j<tlen) { if(k==-1||t[j]==t[k]) next1[++j]=++k; else k=next1[k]; } }
next1[tlen]=我们输入的完整字符串的相同前后缀,然后tlen-next1[tlen]=循环节的长度;因为,一个字符串,例如:abcdabcd本身就是循环字符串或者abcdxyzabc这样的,所以当我们求出了tlen-next[tlen]
的时候只有三个情况,这个字符串是循环的,这个不是循环的但是字符串末尾有一部分循环节,这个不是循环的,且本身是一个也只有这个一个循环节,所以通过计算前后缀可以得到后面的重复部分,前后缀为0,没有循环节重复,不为零,有重复部分;
完整代码:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<math.h> #include<cstdlib> using namespace std; char t[100500]; int next1[100500]; int tlen; void get_next() { int j,k; j=0;k=-1;next1[0]=-1; while(j<tlen) { if(k==-1||t[j]==t[k]) next1[++j]=++k; else k=next1[k]; } } int main() { int tt; scanf("%d",&tt); while(tt--) { gets(t); tlen=strlen(t); get_next(); int minn=tlen-next1[tlen]; if(tlen!=minn&&(tlen%minn==0)) { printf("0 "); } else printf("%d ",minn-(tlen%minn)); } }