牛客 悠悠碧波/CF126B(kmp)

牛客 悠悠碧波/CF126B(kmp)

题目描述

链接: 牛客链接.
链接: 洛谷题解.
题意:给一个字符串,求出其中最长的一个子串,满足既是前缀也是后缀,且在中间也至少出现过一次

题解

首先前缀和后缀相等,联想到kmp(kan mao pian)算法:
该子串既是以len-1结尾的后缀,也是串中以某一第i位置结尾的后缀,也是整个串的前缀。

(1)首先kmp算法处理出[0,len]位置的next值。
对于[0,len-1]的next存储的是失配的下一匹配位置;[1,len]可看作[0,len-1]中以各个位置为结尾的字符串前缀、后缀相等的子串长度。
(2)对于以len-1结尾的与前缀相等的后缀子串长度,若在[1,len-2]位置中也有相同长度的next[]值 ,则都等于前缀。因此在前缀、串中和后缀都出现满足条件。
故只要对k=next[len-1],若k长度未在[1,len-1]出现,则k=next[k];否则输出当前长度的后缀子串满足条件

代码

#include<cstdio>
#include<string>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;

typedef long long ll;
const int maxn=1e6+10;
int nxt[maxn];
int cnt[maxn];

void getNext(string &p){
	int k=-1,j=0,len=p.length();
	nxt[0]=-1;
	while(j<len){
		if(k==-1||p[k]==p[j]){
			nxt[j+1]=k+1;
			j++; k++;
		}else k=nxt[k];
	}
	for(int i=1;i<len-1;i++) cnt[nxt[i]]++;
}

void Solve(string &S){
	int len=S.length(), k=nxt[len-1];
	while(k>=0&&cnt[k]==0) k=nxt[k]; 
	if(k<=0){
//		k<=0,串中未出现 
		cout<<"Just a legend"<<endl;return;
	}
	for(int i=len-k-1;i<len-1;i++) cout<<S[i];
	cout<<endl; 
}

int main(){
	string S; cin>>S;
	S+='$';
	getNext(S);
	Solve(S); 
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值