[水]悠悠碧波
题目描述
帕秋莉掌握了一种水属性魔法
这种魔法可以净化黑暗
帕秋莉发现对于一个黑暗的咒语s,可以使用这个水元素魔法净化它,净化的咒语是一个最长的字符串t,t满足以下条件:
它是s的前缀
它是s的后缀
除前缀和后缀外,它还在s中出现过至少一次
既然你都学会了,那么净化的工作就交给你了!
输入描述
一行字符串 S,代表黑暗咒语
输出描述
一个字符串 T,表示满足条件的最长净化咒语
样例输入
tqrwantoacthisproblembutqristooweaktodoitqr
样例输出
tqr
备注
对于60%的数据,s长度≤100
对于100%的数据,s长度≤100,000
保证存在可行的净化咒语
题解
直接对字符串hash,从大到小枚举结果字符串的长度,比较前缀后缀的hash值,并在字符串中搜索是否存在相同的子字符串,验证即可。
代码
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=111111,mp=123;
ll hh[maxn],pp[maxn];
int n;
char str[maxn];
ll gethh(int l,int r)
{
return hh[r]-hh[l-1]*pp[r-l+1];
}
bool chack(int len)
{
for(int i=2;i<=n-len;i++){
if(gethh(i,i+len-1)==gethh(1,len)){
return true;
}
}
return false;
}
int main()
{
cin>>str+1;
n=strlen(str+1);
pp[0]=1;
for(int i=1;i<=n;i++){
hh[i]=hh[i-1]*mp+str[i];
pp[i]=pp[i-1]*mp;
}
for(int i=n-1,j=2;i>0;i--,j++){
if(gethh(1,i)==gethh(j, n)){
if(chack(i)){
for(int k=1;k<=i;k++)
cout<<str[k];
cout<<endl;
break;
}
}
}
return 0;
}