您的位置:首页 > 其它

CodeForces 126B Password 【kmp】

2016-10-14 13:13 399 查看
题目:点击打开链接

题意:给出一个字符串,求出最长相同的的前缀子串和后缀子串,使得字符串中也存在该子串(不包括前缀子串和后缀子串)。

思路:显然先将字符串处理出next数组,由于next数组保存的是最长公共前后缀长度减一(即要跳转的那一位),所以字符串最后一位字符存的是大于等于满足条件的子串长度,然后要找到中间的子串,从后往前扫一遍字符串直到最长前缀,若发现next值等于最后一个字符的next值,则该值可能是最长长度,先记录下来,然后观察最后一个字符跳转的位置是否能再次跳转,若可以,则继续往前扫,若某位的next值等于最后一个字符跳转的那个位置的next值,则说明存在相同后缀,记录下其next值,最后综上用最大的next值表示答案子串的长度减一,输出前缀子串即可。

代码:

#include <stdio.h>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <set>
#include <vector>
#include <map>
#define PR pair<int,int>
#define MP make_pair
#define fi first
#define se second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define sqr(x) ((x)*(x))
#define ll long long
#define ull unsigned __int64
const ll INF = 1e18;
const int inf=0x3f3f3f3f;
const int M=200010;
const int N=1000100;
const int MOD=10007;
const double eps=1e-10;
const double pi=acos(-1.0);
using namespace std;

char a
;
int n,nxt
;

int main()
{
int i,j;
scanf("%s",a);
n=strlen(a);
nxt[0]=-1;
for(i=1;i<n;i++)
{
j=nxt[i-1];
while(j>=0&&a[i]!=a[j+1]) j=nxt[j];
nxt[i]=a[i]==a[j+1]?j+1:-1;
}
if(nxt[n-1]==-1) {puts("Just a legend");return 0;}
int ok=0,ans=0;
for(i=n-2;i>nxt[n-1];i--)
{
if(nxt[i]==nxt[n-1]) ok=1,ans=nxt[n-1];
}
if(nxt[nxt[n-1]]!=-1)
{
for(i=nxt[n-1];i>nxt[nxt[n-1]];i--)
{
if(nxt[i]==nxt[nxt[n-1]]) ok=1,ans=max(ans,nxt[nxt[n-1]]);
}
}
if(ok==0) puts("Just a legend");
else
{
for(i=0;i<=ans;i++) printf("%c",a[i]);puts("");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: