传送门:点击打开链接
题意:给一串字符串,向其中加字符(只能在字符串前后加,中间不允许加),使字符串形成循环(如abab,abcabc,aa)
解题思路:其实就是一个kmp变种,需要动一点脑筋
1.判断有无循环节,有则不需要加字符
2.如果没有循环节,看next[siz]
3.例如abcedfab next[siz] = 2(重复部分为ab) -> siz - next[siz]*2>=0 即在字符串后或前加入字符串非重复部分(即cedf)即可
4.例如abcdabcda next[siz] = 5 ->siz - next[siz]*2 < 0 这说明字符串的子串有循环节,找到循环节,下面的操作就很简单了
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<vector>
using namespace std;
typedef long long ll;
const int N = 1e5 + 5;
char a[N];
int nt[N];
void getfill()
{
memset(nt, 0, sizeof(nt));
int siz = strlen(a);
for(int i = 1; i < siz; i++)
{
int j = nt[i];
while(j && a[i] != a[j])
j = nt[j];
nt[i+1] = a[i] == a[j]?j+1:0;
}
}
bool solve()
{
int siz = strlen(a);
if(nt[siz] && siz % (siz - nt[siz]) == 0)
return true;
return false;
}
int ac()
{
int siz = strlen(a);
for(int i = siz - 1; i >= 1; i--)
{
if(nt[i] && i % (i - nt[i]) == 0)
return i;
}
}
int main()
{
int n;
scanf("%d", &n);
while(n--)
{
scanf("%s", a);
int siz = strlen(a);
if(solve())
printf("0\n");
else
{
if(siz - nt[siz] * 2 >= 0)
printf("%d\n", siz - nt[siz] * 2);
else
{
int i = ac();
int tmp = siz - i;
int num = i - nt[i];
printf("%d\n", num - tmp);
}
}
}
}