KMP小麻烦的题。
题目让求使一个字符串可以表示成A^K模式最少需要添加多少字符,只能在头部和尾部添加。
这里在头部和尾部添加效果一样,因为是最后是形成一个循环的环,那么,无论从哪个位置开始,这个环都是循环的,所以在头部和尾部添加字符效果都一样。
为了解决问题,可以先求出字符串最大循环前缀,这个可以通过next数组求得,本博客hdu1358文章有讲解。求出最大循环前缀之后,要判断前缀之后的串是否是前面判断的循环节的子串,如果完全不是,那么整个字符串只能作为一个循环节使用,即至少需要添加n个字符;如果之后的串是循环部分循环节的子串,那么只需要将之后的串补成循环节即可。
代码:
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
using namespace std;
char s[100005];
int p[100005];
int n;
void getnext()
{
for (int i=2;i<=n;i++)
{
int j=p[i-1];
while (j>0&&s[j+1]!=s[i])
j=p[j];
if (s[j+1]==s[i])
j++;
p[i]=j;
}
}
int main()
{
int r;
cin>>r;
while (r--)
{
scanf("%s",s+1);
n=strlen(s+1);
//cout<<n<<endl;
getnext();
p[0]=p[1]=0;
int min=n;
int c=1;
for (int i=n;i>=1;i--)
{
if (i%(i-p[i])!=0)
min--;
else
{
c=i-p[i];
break;
}
}
//cout<<min<<endl;
//cout<<c<<endl;
int ans;
if (p[n]==n-c&&p[n]!=0)
ans=(min-n+c)%c;
else
ans=n;
cout<<ans<<endl;
}
}