CF126B Password

题意翻译

Asterix,Obelix和他们的临时伙伴Suffix、Prefix已经最终找到了和谐寺。然而和谐寺大门紧闭,就连Obelix的运气也没好到能打开它。

不久他们发现了一个字符串S(|S|<=1000000),刻在和谐寺大门下面的岩石上。Asterix猜想那一定是打开寺庙大门的密码,于是就大声将字符串朗读了出来,然而并没有什么事发生。于是Asterix又猜想密码一定是字符串S的子串T。

Prefix认为T是S的前缀,Suffix认为T是S的后缀,Obelix却认为T应该是S中的某一部分,也就是说,T既不是S的前缀,也不是S的后缀。

Asterix选择子串T来满足所有伙伴们的想法。同时,在所有可以被接受的子串变形中,Asterix选择了最长的一个(因为Asterix喜欢长的字符串)当Asterix大声读出子串T时,寺庙的大门开了。 (也就是说,你需要找到既是S的前缀又是S的后缀同时又在S中间出现过的最长子串)

现在给你字符串S,你需要找到满足上述要求的子串T。

输入格式:

一个长度在[1,1000000]间的只包含小写字母的字符串S。

输出格式:

输出子串T,如果T不存在,输出 "Just a legend",不包含引号。

分析

使用z函数 , 。。。 没了

代码中最后的for循环是 , 先找到前缀、后缀 , 最后再判断是否有在中间出现的相同的串 , 又因为是要求最大的 , 所以第一扫到的是最优的

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N = 1e6+100;
int n;
int z[N] , t[N];
char c[N];
int main()
{
    scanf("%s",c); n = strlen(c);
    for(int i = 1 , l = 0 , r = 0 ; i < n ; ++i)
    {
        if(i <= r) z[i] = min(z[i - l] , r - i + 1);
        while(i + z[i] < n && c[i + z[i]] == c[z[i]]) z[i]++;
        if(i + z[i] - 1 > r) r = i + z[i] - 1 , l = i;
    }
    for(int i = 1 ; i < n ; ++i)
        if(i + z[i] == n) // i 当前位置 , z[i] 是长度
        {
            for(int j = 1 ; j < i ; ++j)
                if(z[j] >= z[i])
                {printf("%s" , c+i); return 0;}
        }
    puts("Just a legend");
    return 0;
}
原文地址:https://www.cnblogs.com/R-Q-R-Q/p/12123034.html