luogu4595 [COCI2011-2012#5] POPLOCAVANJE 后缀自动机


看着就像后缀自动机....

然后搜了一下,网上一大把的(AC)自动机

嗯......

不管了,打一个试试

然后就过了(QAQ)


我们考虑对于每个点(i)求出它往前最长能匹配的子串的长度

可以对街道串建出后缀自动机

把所有的(L)在后缀自动机上走

走到的串就打个标记,最后顺着(parent)树下传一遍即可


#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

#define ri register int
#define ll long long
#define rep(io, st, ed) for(ri io = st; io <= ed; io ++)
#define drep(io, ed, st) for(ri io = ed; io >= st; io --)

const int sid = 500060;

char s[sid];
int n, m, id = 1;
int fa[sid], mx[sid], val[sid], rig[sid];
int go[sid][26];

int extend(int lst, int c, int pos) {
    int p = lst, np = ++ id;
    rig[np] = pos; mx[np] = mx[p] + 1;
    for( ; p && !go[p][c]; p = fa[p])
        go[p][c] = np;
    if(!p) fa[np] = 1;
    else {
        int q = go[p][c];
        if(mx[p] + 1 == mx[q]) fa[np] = q;
        else {
            int nq = ++ id;
            mx[nq] = mx[p] + 1;
            fa[nq] = fa[q]; fa[np] = fa[q] = nq;
            memcpy(go[nq], go[q], sizeof(go[q]));
            for( ; p && go[p][c] == q; p = fa[p])
                go[p][c] = nq;
        }
    }
    return np;
}

void find(char *s) {
    int n = strlen(s + 1);
    int now = 1;
    rep(i, 1, n) {
        int opt = s[i] - 'a';
        if(!go[now][opt]) return;
        now = go[now][opt];
    }
    val[now] = max(val[now], n);
}

int nc[sid], ip[sid], na[sid];
void solve() {
    rep(i, 1, id) nc[mx[i]] ++;
    rep(i, 1, n) nc[i] += nc[i - 1];
    rep(i, 1, id) ip[nc[mx[i]] --] = i;
    rep(i, 1, id) {
        int o = ip[i];
        val[o] = max(val[o], val[fa[o]]);
        if(rig[o]) {
            int L = rig[o] - val[o] + 1, R = rig[o];
            na[L] ++; na[R + 1] --;
        }
    }
    rep(i, 1, n) na[i] += na[i - 1];
    int ans = 0;
    rep(i, 1, n) if(!na[i]) ans ++;
    printf("%d
", ans);
}
    
int main() {
    cin >> n;
    scanf("%s", s + 1);
    
    int lst = 1;
    rep(i, 1, n) lst = extend(lst, s[i] - 'a', i);
    
    cin >> m;
    rep(i, 1, m) {
        scanf("%s", s + 1);
        find(s);
    }
    
    solve();
    return 0;
}

不知道为啥机房的人之后都写了后缀自动机....

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