B. Password(KMP)

Problem - 126B - Codeforces

Asterix、Obelix和他们的临时伙伴Suffix和Prefix终于找到了和谐寺。然而,它的门被牢牢地锁住了,即使是Obelix也没能打开它们。

过了一会儿,他们发现在寺庙大门下面的一块岩石上刻着一个字符串。亚力认为那是打开神庙的密码,于是大声念出这根弦。然而,什么也没有发生。然后,Asterix认为密码是字符串s的某个子串t。

前缀认为子串t是字符串s的开头;后缀认为子串t应该是字符串s的结尾;而Obelix认为t应该位于字符串s的某个地方,也就是说,t既不是它的开头,也不是它的结尾。

Asterix选择了子串t,以取悦他的所有同伴。此外,在所有可接受的变体中,Asterix选择了最长的一个(因为Asterix喜欢长字符串)。当Asterix大声读出子串t的时候,神庙的门就打开了。

找到子串t,或者确定这样的子串不存在,上面所写的只是一个美好的传说而已。

输入
给你一个字符串s,其长度可以从1到106(包括)不等,由小的拉丁字母组成。

输出
打印字符串t。如果不存在合适的t字符串,则打印 "Just a legend",不加引号。

例子
inputCopy
fixprefixsuffix
outputCopy
固定
输入复制
abcdabc
输出拷贝

Just a legend

题解:

给定一个字符串,找出其中一个最长的子串,使得这个子串既是前缀又是后缀又在中间出现

是不是很像kmp的next的数组

next数组定义为0到当前的最长相同前缀与后缀的长度(不包括当前i本身)

kmp处理完字符串后我们可以得到一个next数组

先标记1~n-1的出现过的ne数组

我们从ne[n]开始(注意是n,未被标记)

t = ne[n]代表目前整个s串中为这个字符串的最长的相同前缀与后缀的长度

然后循环往前遍历

t = ne[t],如果t被标记过说明存在

重点说明t = ne[t]

t代表目前t之前0~t-1字符串的最长的相同前缀与后缀的长度

这个t肯定是如果t存在,由于前面的ne[t]是由ne[n]转变过来的,字符串后面的后缀也相等

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<algorithm>
#include<string>
#include<map>
using namespace std;
#define int long long
char s[1000050];
int ne[1000050];
int p[1000050];
int n;
void kmp()
{
	int i = 0,j = -1;
	ne[0] = -1;
	while(i < n)
	{
		if(j == -1||s[j] == s[i])
		{
			j++;
			i++;
			ne[i] = j;
		}
		else
		{
			j = ne[j];
		}
	}
	for(int i = 1;i < n;i++)
	{
		p[ne[i]]++;
	}
}
void solve()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin >> s;
	n = strlen(s);
	kmp();
	int t = ne[n];
	while(t)
	{
		if(p[t])
		{
			for(int i = 0;i < t;i++)
			{
				cout<<s[i];
			}
			return ;
		}
		t = ne[t];
	}
	cout<<"Just a legend";
	
}
signed main()
{
	int t = 1;
//	cin >> t;
	while(t--)
	{
		solve();
	}
} 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值