码迷,mamicode.com
首页 > 其他好文 > 详细

[POI2006]OKR-Periods of Words

时间:2018-09-25 18:00:26      阅读:138      评论:0      收藏:0      [点我收藏+]

标签:line   include   https   cpp   ++   while   rds   long   des   

Description

Luogu3435
对一个字符串\(A\),定义其周期\(Q\)为,\(Q\)\(A\)的前缀(\(Q!=A\))且\(A\)\(QQ\)的前缀(\(A\)可以等于\(QQ\))。求一个字符串的所有前缀的最长周期的长度之和。

Solution

首先观察周期的定义,可以发现,一旦该字符串有一个前缀等于该字符串的一个后缀,那么这个字符串就是有周期的,与前后缀有关的那就是KMP了。而要求周期最长,就是要求该前缀最短,转化问题之后就可以用KMP解决了。但是,sb的我竟然在KMP的过程中xjb乱跳,直接就跳到最短的了,可是这样会挂啊!考虑这样的一个字符串abacabac,如果在KMP里就处理答案的话就会影响next数组的求解,所以要在KMP之后求答案。

哦对了,求答案的时候可以记忆化一下。

Code

#include <cstdio>

typedef long long LL;
const int N = 1e6 + 10;

char s[N];
int nxt[N]; 
LL ans;
int n;

int main() {
    scanf("%d", &n);
    scanf("%s", s+1);
    nxt[0] = -1;
    for (int i = 1; i <= n; ++i) {
        int t = nxt[i-1];
        while (t != -1 && s[t+1] != s[i]) t = nxt[t];
/*      这里不能有这句话啊!!!!!!!!!!!!!!! 
        if (t != -1) while (nxt[t] != -1 && s[nxt[t] + 1] == s[i]) t = nxt[t];
*/      nxt[i] = t + 1;     
    }
    for (int i = 1; i <= n; ++i) {
        int t = nxt[i];
        while (nxt[t] > 0) t = nxt[t];
        if (nxt[i]) nxt[i] = t; // 记忆化一下 
        if (t) ans += i - t; 
    }
    printf("%lld\n", ans);
    return 0;
}

[POI2006]OKR-Periods of Words

标签:line   include   https   cpp   ++   while   rds   long   des   

原文地址:https://www.cnblogs.com/wyxwyx/p/poi2006okrp.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!