1. 程式人生 > 實用技巧 >題解 P4544 【[USACO10NOV]Buying Feed G】

題解 P4544 【[USACO10NOV]Buying Feed G】

第一遍讀完這道題,這不就是個裸的KMP板子嗎,然後迅速打出了KMP,發現並過不了樣例2,於是又仔細讀了一下題,發現讀漏了一個條件,即需要在中間也出現過,因為我們知道,KMP中的next陣列存的是相同的字首和字尾的長度,那麼只需要找在中間出現過字首長度,並標記一下就行了,最後在匹配的時候多判斷一下。

詳見程式碼

#include<iostream>
#include<cstdio>
using namespace std;
const int N = 1e6 + 5;

string s;
int net[N], num[N];
bool is[N];

int main()
{
    cin >> s;
    for (int i = 1, j = 0; s[i]; i++)
    {
        while (j && s[i] != s[j])
            j = net[j - 1];
        if (s[i] == s[j])
            j++;
        net[i] = j;
    }//求next
    int len = s.length();
    for (int i = 1, j = 0; i < len - 1; i++)
    {
        while (j && s[i] != s[j])
            j = net[j - 1];
        if (s[i] == s[j])
            j++;
        is[j] = true;
    }//找出中間出現過的字首的長度
    int j = 0;
    for (int i = 0; i < len; i++)
    {
        while (j && s[i] != s[j])
            j = net[j - 1];
        if (s[i] == s[j])
            j++;
        while (j && !is[j])
            j = net[j - 1];//判斷是否在中間出現過
    }//匹配
    if (!j)
        cout << "Just a legend";
    else
        for (int i = 0; i < j; i++)
            cout << s[i];
    return 0;
}