HDU3746
题目太长不贴了
这道题很巧妙,给定一个字符串S,求最少在首尾添加几个字符后,S变为一个循环了n次的字符串(n>1)。
假设我们有一个循环串S[]=”abcabcabc”,我们根据KMP求一次next数组,就可以通过next[strlen[S]]得到一个循环节的位置从而求出循环节的长度,显然,循环节能被S整除。如果S[]=”abcdeabab”,我们按上面方法得到的循环节并不能被S整除,差了多少呢,就是差了”cde”的长度,具体怎么算”cde”长度见代码。
/**
* hdu3946
* KMP
* 按书上的写了一遍
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int mmax = 100005;
int lena;
int lens;
void get_next(char * s, int * next1)
{
int i = 0;
int j = -1;
next1[0] = -1;
//为啥是<,后面有i++
while(i < lens)
{
if(j == -1 || s[j]==s[i])
{
i++;
j++;
next1[i]=j;
}
else
j=next1[j];
}
}
//void get_next(char * s, int * next1)
//{
// int i = 0;
// int j = -1;
// next1[0] = -1;
// while(s[i] != '\n')
// {
// while(j != -1 && s[i] != s[j])
// {
// j = next1[j];
// }
// next1[++i] = ++j;
// }
//}
int main()
{
int t;
scanf("%d",&t);
char s[mmax];
int next1[mmax];
while(t--)
{
scanf("%s", s);
lens = strlen(s);
get_next(s, next1);
// for(int i = 0; i < lens; i++)
// {
// printf("%d ", next1[i]);
// }
// printf("\n");
int ans = lens;
int i = next1[lens];
int k,q,p;
while(i!=-1)
{
k = lens-i;
q = lens%k;
p = (k-q)%k;
if(lens+p>=k*2)
ans = min(ans,p);
i = next1[i];
}
printf("%d\n", ans);
}
return 0;
}