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;
}
posted @ 2020-09-18 22:52  C锥  阅读(128)  评论(0编辑  收藏  举报