题目链接:Problem - 4763 (hdu.edu.cn)
先来简单描述下题意:给你一个字符串,让你找出来一个最长子串,使得这个子串在原来字符串的开头结尾以及中间都出现过,且三部分不能含有重叠部分。
其实这道题就是KMP+暴力,也不能完全算是暴力,还有一点点的优化,就是我们枚举公共前后缀,然后直接用KMP匹配前缀和中间部分,如果匹配成功说明这个前缀是符合题意的,如果不匹配就调用前缀的最长公共前后缀继续匹配,直到匹配成功或者前缀长度为0为止。
下面上代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
const int N=1e6+10;
char s[N],p[N];
int len,ne[N];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%s",s+1);
len=strlen(s+1);
for(int i=2,j=0;i<=len;i++)
{
while(j&&s[j+1]!=s[i]) j=ne[j];
if(s[j+1]==s[i]) j++;
ne[i]=j;
}
int t=ne[len];//t为满足题意的最长子串的长度
while(t>len/3) t=ne[t];//先求出可能满足题意的最长公共前后缀长度
bool flag=false;
while(t)
{
if(flag) break;
//用当前公共前后缀与中间部分进行匹配
for(int i=t+1,j=0;i<=len-t;i++)
{
while(j&&s[j+1]!=s[i]) j=ne[j];
if(s[j+1]==s[i]) j++;
if(j==t)
{
flag=true;
break;
}
}
if(!flag) t=ne[t];
}
printf("%d\n",t);
}
return 0;
}
本文介绍了一种使用KMP算法和暴力搜索相结合的方法,解决了一个字符串问题:寻找同时在开头、结尾和中间出现过的最长子串,且不包含重叠部分。通过计算公共前后缀和匹配子串实现高效求解。
1380

被折叠的 条评论
为什么被折叠?



