Codeforces 126B. Password (Next 数组 + DP / Hash)

Description
Asterix, Obelix and their temporary buddies Suffix and Prefix has finally found the Harmony temple. However, its doors were firmly locked and even Obelix had no luck opening them.
A little later they found a string s, carved on a rock below the temple’s gates. Asterix supposed that that’s the password that opens the temple and read the string aloud. However, nothing happened. Then Asterix supposed that a password is some substring t of the string s.
Prefix supposed that the substring t is the beginning of the string s; Suffix supposed that the substring t should be the end of the string s; and Obelix supposed that t should be located somewhere inside the string s, that is, t is neither its beginning, nor its end.
Asterix chose the substring t so as to please all his companions. Besides, from all acceptable variants Asterix chose the longest one (as Asterix loves long strings). When Asterix read the substring t aloud, the temple doors opened.
You know the string s. Find the substring t or determine that such substring does not exist and all that’s been written above is just a nice legend.

Input
You are given the string s whose length can vary from 1 1 1 to 1 0 6 10^6 106 (inclusive), consisting of small Latin letters.

Output
Print the string t. If a suitable t string does not exist, then print “Just a legend” without the quotes.

Examples
Input
fixprefixsuffix
Output
fix

Input
abcdabc
Output
Just a legend

Main idea
求给定字符串中是否存在一个子串,既是前缀又是后缀,也是非前后缀

Solution 1
利用next数组 + DP 求出所有相同前后缀的出现次数,出现次数大于2的最长前后缀即为答案
和这题相似:Codeforces 432D

Solution 2
hash暴力(居然没有TLE)

Code 1

#include <bits/stdc++.h>
#define clr(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e6 + 5;
char s[maxn];
int nex[maxn];
void find_nex(int m){
	int i,j;
	j = nex[1] = 0;
	i = 2;
	while(i <= m){
		while(j && s[j+1] != s[i]) j = nex[j];
		if(s[j+1] == s[i]) j++;
		nex[i++] = j;
	}
}

int num[maxn];
void solve(){
	int n = strlen(s+1);find_nex(n);
	for(int i = n;i > 0;--i){
		num[i]++;
		num[nex[i]] += num[i];
	}
	int l = 0;
	for(int i = n;i > 0;i = nex[i]){
		if(num[i] >= 3){
			l = i;break;
		}
	}
	if(l == 0) printf("Just a legend\n");
	else{
		for(int i = 1;i <= l;++i) printf("%c", s[i]);
		printf("\n");
	} 
	return ;
}
int main(){
	scanf("%s",s+1);
	solve();
	return 0;
}

Code 2

#include <bits/stdc++.h>
#include <cstring>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int base1 = 13331;
const int base2 = 131;
const int mod1 = 1e9 + 7;
const int mod2 = 19260817;
const int maxn = 1e6 + 5;
ll p1[maxn],p2[maxn];
ll hash1[maxn],hash2[maxn];
int main(){
	p1[0] = p2[0] = 1;for(int i = 1;i < maxn;++i) p1[i] = (p1[i-1] * base1) % mod1, p2[i] = (p2[i-1] * base2) % mod2;
	string s;cin >> s;
	int len = s.length();
	for(int i = 1;i <= len;++i){
		hash1[i] = (hash1[i-1]*base1+s[i-1])%mod1;
		hash2[i] = (hash2[i-1]*base2+s[i-1])%mod2;
	}
	int pos = 0;
	for(int i = len - 2;i >= 1;--i){
		ll pre1 = hash1[i], pre2 = hash2[i];
		ll suf1 = ((hash1[len] - hash1[len-i]*p1[i])%mod1+mod1)%mod1, suf2 = ((hash2[len] - hash2[len-i]*p2[i])%mod2+mod2)%mod2;
		if((pre1 != suf1) || (pre2 != suf2)) continue;
		for(int j = 2;j + i - 1 < len;++j){
			ll h1 = ((hash1[j+i-1] - hash1[j-1]*p1[i])%mod1+mod1)%mod1, h2 = ((hash2[j+i-1] - hash2[j-1]*p2[i])%mod2+mod2)%mod2;
			if((h1 == pre1) && (h2 == pre2)) {
				cout << s.substr(0,i) << endl;
				return 0;
			}
		}
	}
	cout << "Just a legend" << endl;
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值