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

bzoj4974 字符串大师 KMP

时间:2018-11-12 20:55:10      阅读:199      评论:0      收藏:0      [点我收藏+]

标签:space   bre   main   ret   har   http   temp   cstring   技术   

技术分享图片

明显的,有$next[i] = i - pre[i]$

根据$next[i]$构造比根据$pre[i]$简单

如果$next[i] \neq 0$,那么我们可以直接取前面的结果

否则,我们可以暴力的寻找$next[i - 1], next[next[i - 1]] ...$后一位中最小没有出现过的字符

暴力的复杂度为$O(n)$

 

不妨考虑有一棵$next$树

最坏情况下,我们会从每个叶子节点走到根一遍

对于需要走的每个叶子节点$x$,都有$next[x + 1] = 0$

并且从叶子节点走到根的复杂度为$O(next[x])$

由于有$next[i] \leq next[i - 1] + 1$,因此对于满足$next[x + 1] = 0$的$next[x]$的和不会超过$n$

因此复杂度不超过$O(n)$

 

如果你闲的发慌,可以用可持久化线段树做到$O(n \log \sum)$而不是$O(n \sum)$

其中$\sum$为字符集大小

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
namespace remoon {
    #define de double
    #define le long double
    #define ri register int
    #define ll long long
    #define tpr template <typename ra>
    #define rep(iu, st, ed) for(ri iu = st; iu <= ed; iu ++)
    #define drep(iu, ed, st) for(ri iu = ed; iu >= st; iu --)    
    #define gc getchar
    inline int read() {
        int p = 0, w = 1; char c = gc();
        while(c > 9 || c < 0) { if(c == -) w = -1; c = gc(); }
        while(c >= 0 && c <= 9) p = p * 10 + c - 0, c = gc();
        return p * w;
    }
}
using namespace std;
using namespace remoon;

const int sid = 300050;

int n;
char s[sid];
int nxt[sid];
bool vis[40];

int main() {
    n = read();
    rep(i, 1, n) {
        nxt[i] = i - read();
        if(nxt[i]) s[i] = s[nxt[i]];
        else {
            memset(vis, 0, sizeof(vis));
            for(ri j = nxt[i]; j; j = nxt[j]) 
                vis[s[j + 1] - a] = 1;
            vis[s[1] - a] = 1;
            for(ri j = a; j <= z; j ++)
                if(!vis[j - a]) { s[i] = j; break; }
        }
        printf("%c", s[i]);
    }
    return 0;
}

 

bzoj4974 字符串大师 KMP

标签:space   bre   main   ret   har   http   temp   cstring   技术   

原文地址:https://www.cnblogs.com/reverymoon/p/9948835.html

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