//题目意思是:求最少需要在结尾后面补几个字符才能凑成两个循环
这里主要讲的是hdu3746,没有讲解kmp
有关kmp的博客推荐去看这个博客:(讲得十分漂亮,令人心花怒放:)不过篇幅比较长,需要静下心来慢慢品味u)
https://blog.csdn.net/v_july_v/article/details/7041827
对于这题,先看一下图:
我们再考虑另一种情况:
|——————|——|——————|
0 1 x 2
其中next[len]=x, 0~x与1~2对应那么len-next[len]=0~1(或x~2)是否是周期呢?这个问题我也考虑了许久
根据我的理解来解释下:
因为0~x与1~2是对应的,即相等,又1~x部分是两者共有部分,所以在0处和2处分别取1~x这么长的一段,并且它们都是一样的(结合一下下面的图理解下)
|——|———|——|———|——|
0 x’ 1 x x'' 2
这里0~x’,1~x ,x''~2都是相等的
并且也可以得到x'~1与x~x''相等
结合图可知:
- 当以0~1为周期时,只需在0的前面差入x''~2这段即可,即加入长度为len%(n-x)=len%(n-next[len])
- 当以0~x这段为周期时,只需在2的后面插入1~x这段即可,即加入长度也为len%(n-x)=len%(n-next[len]);
实现代码如下
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 200000+10
int len;
int next1[MAXN];
char sm[MAXN];
void getNext()
{
int j=0;
int k=-1;
next1[0]=-1;
while(j<len)
{
if(k==-1||sm[j]==sm[k])
{
k++;
j++;
next1[j]=k;
}
else
{
k=next1[k];
}
}
}
int main()
{
int t;
scanf("%d",&t);
getchar();
while(t--)
{
scanf("%s",sm);
len=strlen(sm);
getNext();
int T=len-next1[len]; //T为周期
if(len%T==0&&len!=T) //当len==T是应输出的是所有的祖父穿长度len,即T-len%T
{
printf("0\n");
}
else
printf("%d\n",T-len%T);
}
return 0;
}
参考文献:
1.https://blog.csdn.net/xingyeyongheng/article/details/9285709