您的位置:首页 > 产品设计 > UI/UE

2016 UESTC Training for Search Algorithm & String K - 卿大爷的三个女友 KMP、跳转数组

2016-06-10 11:06 477 查看


K - 卿大爷的三个女友


Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others)


Submit
Status

卿大爷发现了一个字符串,他要在上面找到$3$个女朋友的名字。他的一个女朋友名字是字符串的前缀,一个是后缀,还有一个在中间的
某个位置(三者不互相重叠)。他想让你告诉他他女朋友名字的最大长度是多少。也就是说找到一个最长的子串使得它既是前缀又是后缀,
还在中间,求这个子串的长度。


Input

第一行一个数字N(N<=100),代表有N组数据。 接下来N行,每行一个字符串s,1<=|s|<=100000,均由小写字母构成。


Output

对于每组数据,输出最长符合条件子串的长度。


Sample input and output

Sample InputSample Output
5
xy
abc
aaa
aaaaba
aaxoaaaaa

0
0
1
1
2


Source

2016
UESTC Training for Search Algorithm & String


My Solution

KMP 的跳转数组的拓展使用

关键在于KMP思维的转化。思维很重要!先用文本串做个跳转数组。

设文本串长度为len。

我们考虑匹配第len个位置。跳转数组每跳一个位置。

都能保证文本串的前缀==后缀,可以自己手动模拟画个看看。

故只需在剩下的中间部分找有没有匹配的子串即可。

一旦找到了就好了,这个就是最长的了^_^。

复杂度 O(T*n)

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn=1e5 + 8;

int nxt[maxn], len;
char text[maxn];
void getnxt(char *p)
{
nxt[1] = 0;
for(int i = 1, j = 0; i < len; i++){
j = nxt[i];
while(j && p[j] != p[i])
j = nxt[j];
nxt[i+1] = p[j] == p[i] ? j+1 : 0;            //在这里进行初始化了, 故用的时候不要memset了
}
}

bool kmp(char *T,char *P,int n,int m)
{
for(int i=0, j=0; i < n; i++){
while(j && P[j] != T[i])
j = nxt[j];
if(P[j] == T[i])
j++;
if(j == m)
return true;
}
return false;
}

int main()
{
#ifdef LOCAL
freopen("a.txt", "r", stdin);
#endif // LOCAL
int T,j,ans;

scanf("%d",&T);
while(T--){
ans=0;
scanf("%s",text);
len=strlen(text);
getnxt(text);
j = nxt[len];
while(j){
if(len >= 3*j&& kmp(text+j, text, len-2*j, j)){
ans=j;
break;
}
j = nxt[j];
}
printf("%d\n",ans);
}
return 0;
}


Thank you!

------from ProLights
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: