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
Output
Input示例
Output示例
解:预处理出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;
}
题目来源: 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;
}
相关文章推荐
- 51 nod 1304 1304 字符串的相似度(exkmp)
- 51nod(1183)——dp
- 动态规划初步总结(1)(51Nod,CODE[VS]为例题)
- 51 nod 一级算法题 1344 走格子
- 51 NOD 1189 阶乘分数(素因子分解+推公式+求逆元)
- 51 NOD 1024 矩阵中不重复的元素(技巧)
- 51 NOD 1238 最小公倍数之和 V3
- 51Nod——完美字符串
- 51Nod——1295 XOR key(贪心+可持久化字典树)
- 51 nod 1055 最长等差数列(dp)
- 1的数量(51nod)
- 51 nod 1222 最小公倍数计数
- (51nod)1008 - N的阶乘 mod P
- 51 nod 1140
- 高精度运算 51 nod 大数相乘
- 51 Nod 1013 3的幂的和 矩阵链乘法||逆元+快速幂
- 【51nod 1785】数据流中的算法
- 51 Nod 1130 N的阶乘的长度 V2(斯特林近似)
- 51 Nod 1441 质因子筛
- 51 nod 1126 求递推序列的第N项 矩阵快速幂