[水]悠悠碧波

[水]悠悠碧波

题目描述

帕秋莉掌握了一种水属性魔法

这种魔法可以净化黑暗

帕秋莉发现对于一个黑暗的咒语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;
}
posted @ 2020-07-13 22:13  落水清心  阅读(88)  评论(0编辑  收藏  举报