1. 程式人生 > >2018年牛客多校演算法寒假訓練營練習比賽(第五場)C-字串的問題(KMP or find)

2018年牛客多校演算法寒假訓練營練習比賽(第五場)C-字串的問題(KMP or find)

題目連結:https://ac.nowcoder.com/acm/contest/77/C

思路:根據next 陣列各值的含義:代表當前字元之前的字串中,有多大長度的相同字首字尾。例如如果next [j] = k,代表j 之前的字串中有最大長度為k 的相同字首字尾。我們用num陣列存一下去除去開頭和結尾的子串的最長前後綴的長度出現的次數。如果存在次數>=1直接輸出,否則k = Next[k]繼續尋找。找不到就輸出Just a legend。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+7;
int Next[maxn], num[maxn];
string p; int plen;
void getNext()
{
    int j, k; plen = p.length();
    j = 0; k = -1; Next[0] = -1;
    while(j < plen)
    {
    	 if(k == -1 || p[j] == p[k])
        {
        	++j; ++k;
            Next[j] = k;
        }
        else k = Next[k];
    }
}
int main()
{
    cin >> p; getNext();
    for(int i = 2; i < plen-1; i++) num[Next[i]]++;
    int k = Next[plen];
    while(k)
    {
        if(num[k])
        {
            for(int i = 0; i < k; i++)
                cout << p[i];
            return 0;
        }
        k = Next[k];
    }
    puts("Just a legend");
}

思路二:利用string的find函式(find函式原理好像也是kmp)直接查詢模擬。

#include <bits/stdc++.h>
using namespace std;
string s;
string pre, suf, mid, ans = "Just a legend";
int main()
{
    cin >> s;
    int len = s.size(), k = 0;
    while (++k < len)
    {
        pre = s.substr(0, k);
        suf = s.substr(len-k, k);
        if(pre == suf)
        {
            mid = s.substr(1, len-2);
            if(mid.find(pre) < len-1) ans = pre;
        }
    }
    cout << ans << endl;
}