codeforces 126B password

一道锻炼对于 k m p kmp kmp算法中的 p m t pmt pmt数组理解的题
题目链接

题目大意

给定字符串 s s s,需要找到字符串 t t t,使得 t t t满足以下条件: t t t既是 s s s的前缀也是后缀,同时在 s s s内部出现

思路

我们发现 t t t既是后缀又是前缀,这不就是 k m p kmp kmp p m t pmt pmt数组的定义嘛(大佬的博客也叫失配数组或next数组),所以我们可以先求出一个 p m t pmt pmt数组,然后到 s s s中找目标字串。
因为中间字串 t t t只能结束于 s [ 2 ] s[2] s[2] ~ s [ n − 1 ] s[n-1] s[n1]之间,所以 t t t的长度也在 p m t [ 2 ] pmt[2] pmt[2]~ p m t [ n − 1 ] pmt[n-1] pmt[n1]之间,所以我们求 p m t pmt pmt的时候顺便求一个长度最大值 m a ma ma
剩下的就是遍历小于等于 m a ma ma的输出就行了,可以是复杂度 n n n的遍历,也可以是我下面写的方法

ACcode

#include

using namespace std;

const int M = 1e6 + 9;
int pmt[M];

void get_pmt(const string& p) {
    for (int i = 1, j = 0;i < p.size();i++) {
        while (j && p[i] != p[j])j = pmt[j - 1];
        if (p[i] == p[j])j++;
        pmt[i] = j;
    }
}

int main() {
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    string str;cin >> str;
    get_pmt(str);
    int ma = 0;
    for (int i = 1;i < str.size() - 1;i++)ma = max(ma, pmt[i]);
    int k = pmt[str.size() - 1];//长度
    
    while (k > ma)k = pmt[k - 1];
    //为什么k=pmt[k-1]?
    //因为现在的k是大于ma的,而我们要找的是小于ma的,所以直接跳到字符串长度为k的地方,因为我这个是string直接读取的字符串,所以下标就是k-1
    
    if (k) {
        for (int i = 0;i < k;i++)cout << str[i];
    }
    else {
        cout << "Just a legend";
    }
    return 0;
}

你可能感兴趣的:(kmp专题,算法,kmp,失配数组,字符串)