[CF126B] Password

[CF126B] Password - KMP

Description

给你一个字符串S(|S|<=1000000),找到既是S前缀又是S后缀又在S中间出现过(既不是S前缀又不是S后缀)的子串,如果不存在输出“Just a legend”。

Solution

从 n 开始沿着 KMP 的 next 迭代,这些串是备选的,现在要考察他们是否在中间出现

记录下 next 数组中间部分的最大值,当找到第一个长度不超过那个最大值时,就是答案

#include <bits/stdc++.h>
using namespace std;

#define int long long

const int N = 1e6 + 5;

int fail[N], n;
string str;

signed main()
{
    ios::sync_with_stdio(false);

    cin >> str;
    n = str.length();
    str = " " + str;

    fail[1] = 0;
    int j = 0;
    for (int i = 2; i <= n; i++)
    {
        while (j && str[i] != str[j + 1])
            j = fail[j];
        if (str[i] == str[j + 1])
            ++j;
        fail[i] = j;
    }

    int mx = 0;
    for (int i = 2; i < n; i++)
        mx = max(mx, fail[i]);

    int p = fail[n];
    while (p > mx)
        p = fail[p];

    if (p)
    {
        for (int i = 1; i <= p; i++)
            cout << str[i];
    }
    else
    {
        cout << "Just a legend";
    }
}
原文地址:https://www.cnblogs.com/mollnn/p/14430283.html