您的位置:首页 > 其它

51 nod 1286 1286 三段子串(exkmp)

2017-08-23 18:58 721 查看
1286 三段子串


题目来源: Codility

基准时间限制:1 秒 空间限制:131072 KB 分值: 160 难度:6级算法题


 收藏


 关注

给定一个字符串S,找到另外一个字符串T,T既是S的前缀,也是S的后缀,并且在中间某个地方也出现一次,并且这三次出现不重合。求T最长的长度。
例如:S = "abababababa",其中"aba"既是S的前缀,也是S的后缀,中间还出现了一次,并且同前缀后缀均不重合。所以输出"aba"的长度3。如果找不到一个符合条件的字符,输出0。

Input
输入字符串S。(1 <= L <= 1000000, L为S的长度)


Output
输出这个最长的子串的长度。


Input示例
abababababa


Output示例
3


解:预处理出exkmp的next数组,遍历中间字符串与前缀的最大共同长度,遍历后缀求最大长度

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N= 1e6+1000;
char s1
, s2
;
int extend
, nex
;
void getnext(char a[],int len)
{
int k=0, i=1;
nex[0]=len;
while(k+1<len&&a[k]==a[k+1])++k;
nex[1]=k;
k=1;
while(++i<len)
{
int p=k+nex[k]-1;
nex[i]=min(nex[i-k],max(p-i+1,0));
while(i+nex[i]<len&&a[nex[i]]==a[i+nex[i]]) ++nex[i];
if(i+nex[i]>k+nex[k]) k=i;
}
return ;
}
void exkmp(char a[],char b[],int len,int len2)
{
getnext(a,len);
int k=0, i=0;
while(k<len2&&a[k]==b[k]) ++k;
extend[0]=k;
k=0;
while(++i<len2)
{
int p=k+extend[k]-1;
extend[i]=min(nex[i-k],max(p-i+1,0));
while(i+extend[i]<len2&&a[extend[i]]==b[i+extend[i]]) ++extend[i];
if(i+extend[i]>k+extend[k]) k=i;
}
return ;
}
char v[1000];
int a
;
int main()
{

scanf("%s",s1);
int len=strlen(s1);
if(len<3)
{
printf("0\n");
return 0;
}
getnext(s1,len);
int k=1;
a[0]=0;
for(int i=len-len/3; i<len; i++)
{
if(nex[i]==len-i) a[k++]=nex[i];
}
a[k]=N+10;
if(k==1)
{
printf("0\n");
return 0;
}
k++;
sort(a,a+k);
int m=0, ans=0;
for(int i=1; i<len-1; i++)
{
m=min(i,nex[i]);
if(m==0) continue;
int pos=lower_bound(a,a+k,m)-a;
int l=0, r=pos, tmp=0;
while(l<=r)
{
int mid=(l+r)/2;
if(a[mid]<=m&&i+a[mid]-1<len-a[mid]) tmp=a[mid],l=mid+1;
else r=mid-1;
}
ans=max(ans,tmp);
}
printf("%d\n",ans);

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