1. 程式人生 > 實用技巧 >P3435 [POI2006]OKR-Periods of Words KMP演算法

P3435 [POI2006]OKR-Periods of Words KMP演算法

P3435 [POI2006]OKR-Periods of Words

題目連結

​ KMP演算法。

​ 一開始主要是題意沒搞懂,搞懂了就好寫了。題目大意就是:給定一個字串,讓你求這個字串的每一個前驅的proper前驅的長度總和,proper前驅的意思就是某個字串\(x\)的一個不為自己的前驅,複製兩遍後拼接起來的字串為\(y\),使\(x\)\(y\)的前驅。

(使用了洛谷 @Orion545dalao的圖)

​ 圖中黑色的是字串\(x\),藍色的就是我們要找的proper前驅。利用\(next\)陣列的性質,我們可以使兩段綠色的部分相同,這樣當藍色的部分複製兩遍拼接起來後得到的字串\(y\)

\(x\)肯定是\(y\)的前驅。所以我們現在找到一個不為0的最小的\(next\)就好了,讓\(ans += len_x - next\)

​ 注意要使用一個優化:\(next[x]\)等於綠色部分長度。不然會TLE。

#include <bits/stdc++.h>

using namespace std;

const int N = 1e6 + 5;
int n, j, nxt[N];
long long ans;
char ch[N];

int main() {

    cin >> n; cin >> ch + 1;
    
    for(int i = 2;i <= n; i++) {
        while(j && ch[j + 1] != ch[i]) j = nxt[j];
        j += (ch[j + 1] == ch[i]); nxt[i] = j;
    }

    for(int i = 1;i <= n; i++) {
        j = i;
        while(nxt[j]) j = nxt[j];
        if(nxt[i]) nxt[i] = j; //優化
        ans += i - j;
    }

    printf("%lld", ans);

    return 0;
}