P4081 [USACO17DEC]Standing Out from the Herd P

题面

自己去看吧

题解

明显的广义后缀自动机, 关键怎么算, 只能按字符串出遍历每个节点

再根据link去标记节点, 最后根据标记去算贡献

struct EXSAM { //trie一样的空间 N * M, 再建自动机为 N * M << 1
    static const int N = 1e5 + 5, M = 26, C = 'a', NUM = 15;//N字串总长度,NUM字符串个数
    struct Node { int len, fa, ne[M]; } tr[N << 1];
    int tot, mxlen, tax[N << 1], rk[N << 1];
    int newNode() { return memset(tr[++tot].ne, 0, sizeof tr[0].ne), tot; }
    void init() { 
        memset(tr[0].ne, 0, sizeof tr[0].ne); 
        tot = mxlen = 0; tr[0].fa = -1;
    }
    int insertSAM(int las, int ch) {
        int cur = tr[las].ne[ch], p = tr[las].fa;
        tr[cur].len = tr[las].len + 1;
        for (; p != -1 && !tr[p].ne[ch]; p = tr[p].fa) tr[p].ne[ch] = cur;
        if (p == -1) return tr[cur].fa = 0, cur;
        int q = tr[p].ne[ch];
        if (tr[p].len + 1 == tr[q].len) return tr[cur].fa = q, cur;
        int nq = ++tot; tr[nq].len = tr[p].len + 1; tr[nq].fa = tr[q].fa;
        rep (i, 0, M - 1) tr[nq].ne[i] = tr[tr[q].ne[i]].len ? tr[q].ne[i] : 0;
        for (; p != -1 && tr[p].ne[ch] == q; p = tr[p].fa) tr[p].ne[ch] = nq;
        return tr[cur].fa = tr[q].fa = nq, cur;
    }
    int insertTrie(int cur, int ch) {
        if (!tr[cur].ne[ch]) tr[cur].ne[ch] = newNode();
        return tr[cur].ne[ch];
    }
    int insert(const char *s) {
        int len = 0;
        for (int& i = len, p = 0; s[i]; p = insertTrie(p, s[i++] - C));
        return umax(mxlen, len), len;
    }
    void build() {
        queue<pair<int, int>> q;
        rep (i, 0, M - 1) if (tr[0].ne[i]) q.push({ i, 0 });
        while (!q.empty()) {
            PII it = q.front(); q.pop();
            int las = insertSAM(it.se, it.fi);
            rep (i, 0, M - 1) if (tr[las].ne[i]) q.push({ i, las });
        }
    }
    int tag[N << 1], ans[N];
    void dfs(int p, int id) {
        for (; p != -1 && tag[p] != id && tag[p] != -1; p = tr[p].fa) tag[p] = tag[p] ? -1 : id;
    }
    void difsub(char *s, int* len, int n) {
        rep (i, 1, n) for (int j = len[i - 1], p = tr[0].ne[s[j] - C]; j < len[i]; p = tr[p].ne[s[++j] - C]) dfs(p, i);
        rep (i, 0, tot) if (tag[i] != -1) ans[tag[i]] += tr[i].len - tr[tr[i].fa].len;
        rep (i, 1, n) cout << ans[i] << '
';
    }
} exSam;

const int N = 1e5 + 5, inf = 0x3f3f3f3f;

int n, m, _, k;
int len[N], ans[N];
char s[N];

int main() {
    exSam.init(); read(n);
    rep (i, 1, n) { cin >> s + len[i - 1]; len[i] = exSam.insert(s + len[i - 1]) + len[i - 1]; }
    exSam.build(); exSam.difsub(s, len, n);
    return 0;
}
原文地址:https://www.cnblogs.com/2aptx4869/p/14173883.html