zoukankan      html  css  js  c++  java
  • bzoj 4545 DQS 的 Trie

    老年选手不会 SAM 也不会 LCT 系列

    我的数据结构好菜啊 qnq

    一颗 Trie 树,$q$ 次询问,每次可以是:

    1.求这棵树上本质不同的子串数量

    2.插入一个子树,保证总大小不超过 $100000$

    3.询问一个字符串在 Trie 树上出现过多少次,保证所有询问串总长度不超过 $100000$

    sol:

    第一问显然就是个广义 SAM,可以在每次 extend 的时候顺便算出来

    第二问和第三问要求动态维护 parent 树的子树 size,差分一下就变成了链加和单点查询,LCT 维护一下即可

    注意的几个细节:

    如果你要匹配一个整串,串在 SAM 上跑的时候是直接走 Trans 边,不跳 parent

    (注意区别于,如果你要匹配一个串的子串,在 SAM 上跑的时候要跳 parent ,注意这两个不一样

    LCT 的 link 和 cut,如果你使用的是不 makeroot 的偷懒写法,是不满足交换律的,一定都是一个方向(从上往下 link / cut)

    为什么我不 makeroot 啊(平时啥都敢写系列

    #include <bits/stdc++.h>
    #define LL long long
    #define rep(i, s, t) for (register int i = (s), i##end = (t); i <= i##end; ++i)
    #define dwn(i, s, t) for (register int i = (s), i##end = (t); i >= i##end; --i)
    using namespace std;
    inline int read() {
        int x = 0,f = 1; char ch = getchar();
        for(; !isdigit(ch); ch = getchar())if(ch == '-') f = -f;
        for(; isdigit(ch); ch = getchar())x = 10 * x + ch - '0';
        return x * f;
    }
    const int maxn = 400010;
    #define ls ch[x][0]
    #define rs ch[x][1]
    char s[maxn];
    int n, node[maxn];
    int ch[maxn][2], fa[maxn], tag[maxn], val[maxn], st[maxn], top;
    inline int isroot(int x) { return (ch[fa[x]][0] != x) && (ch[fa[x]][1] != x); }
    inline void rotate(int x) {
        int y = fa[x], z = fa[y];
        int l = (ch[y][1] == x), r = l ^ 1;
        if(!isroot(y)) ch[z][ch[z][1] == y] = x;
        fa[x] = z; fa[ch[x][r]] = y; fa[y] = x;
        ch[y][l] = ch[x][r]; ch[x][r] = y;
    }
    inline void pushdown(int x) {
        if(x && tag[x]) {
            if(ls) tag[ls] += tag[x], val[ls] += tag[x];
            if(rs) tag[rs] += tag[x], val[rs] += tag[x];
            tag[x] = 0;
        }
    }
    inline void splay(int x) {
        st[top = 1] = x;
        for(int i = x; !isroot(i); i = fa[i]) st[++top] = fa[i];
        for(int i = top; i; i--) pushdown(st[i]);
        while(!isroot(x)) {
            int y = fa[x], z = fa[y];
            if(!isroot(y)) {
                if(ch[y][0] == x ^ ch[z][0] == y) rotate(x);
                else rotate(y);
            }
            rotate(x);
        }
    }
    inline void access(int x) {
        for(int y = 0; x; y = x, x = fa[x]) {
            splay(x);
            rs = y;
        }
    }
    inline void link(int x, int y) {
        fa[y] = x; //cerr << "link :" << x  << " " << y << endl;
        access(x); splay(x);
        val[x] += val[y];
        tag[x] += val[y];
    }
    inline void cut(int x, int y) {
        access(y); splay(y);  //cerr << "cut :" << x  << " " << y << endl;
        val[x] -= val[y];
        tag[x] -= val[y];
        fa[x] = 0; ch[y][0] = 0;
    }
    int tr[maxn][7], mxlen[maxn], pre[maxn], root, dfn;
    LL ans;
    int extend(int last, int c) {
        int p = last, np = last = ++dfn;
        mxlen[np] = mxlen[p] + 1;
        for(; p && !tr[p][c]; p = pre[p]) tr[p][c] = np;
        if(!p) pre[np] = root, link(root, np);
        else {
            int q = tr[p][c];
            if(mxlen[p] + 1 == mxlen[q]) pre[np] = q, link(q, np);
            else {
                int nq = ++dfn;
                mxlen[nq] = mxlen[p] + 1;
                pre[nq] = pre[q];
                link(pre[q], nq); 
                memcpy(tr[nq], tr[q], sizeof(tr[nq]));
                for(; p && tr[p][c] == q; p = pre[p]) tr[p][c] = nq;
                cut(pre[q], q);
                pre[np] = pre[q] = nq;
                link(pre[q], q);link(pre[np], np); 
            }
        }
        ans += ((LL)mxlen[np] - (LL)mxlen[pre[np]]);
        access(np); splay(np);
        val[np]++; tag[np]++;
    //    cerr << np << endl;
        return np;
    }
    int first[maxn], to[maxn << 1], nx[maxn << 1], va[maxn], cnt;
    int vis[maxn], clo, par[maxn];
    inline void add(int u, int v, int w) {
        to[++cnt] = v;
        va[cnt] = w;
        nx[cnt] = first[u];
        first[u] = cnt;
    }
    void dfs(int x) {
        for(int i=first[x];i;i=nx[i]) {
            if(to[i] == par[x] || vis[to[i]] != clo) continue;
            par[to[i]] = x;
            node[to[i]] = extend(node[x], va[i]);
            dfs(to[i]);
        }
    }
    int run() {
        int now = root, len = strlen(s + 1);
        rep(i, 1, len) {
        //    while(now && !tr[now][s[i] - 'a']) now = pre[now];
            now = tr[now][s[i] - 'a'];
        }
        //cerr << now << endl;
        if(!now) return 0;
        access(now); splay(now);
        return val[now];
    }
    int main() {
        //freopen("8.in","r",stdin);
        //freopen("8oo.out","w",stdout);
        //freopen("8oo_err","w",stderr);
        root = ++dfn; node[1] = root;
        read(); n = read(); clo++; 
        rep(i, 2, n) {
            int u = read(), v = read();
            char ch; cin >> ch;
            add(u, v, ch - 'a'); add(v, u, ch - 'a');
            //cout << ch << endl;
            vis[u] = vis[v] = clo;
        } dfs(1);
        int q = read();
        while(q--) {
            int opt = read();
            if(opt == 1) printf("%lld
    ", ans);
            else if(opt == 2) {
                int ri = read(), si = read(); clo++;
                rep(i, 2, si) {
                    int u = read(), v = read();
                    char ch; cin >> ch;
                    add(u, v, ch - 'a'); add(v, u, ch - 'a');
                    vis[u] = vis[v] = clo;
                } dfs(ri);
            }
            else if(opt == 3) {
                scanf("%s", s + 1);
                printf("%d
    ", run());
            }
            //int xo = 0;
        //    rep(i, 1, n) xo ^= node[i];
            //cerr << xo << endl;
        }
    }
    View Code
  • 相关阅读:
    【leetcode】1630. Arithmetic Subarrays
    【leetcode】1629. Slowest Key
    【leetcode】1624. Largest Substring Between Two Equal Characters
    【leetcode】1620. Coordinate With Maximum Network Quality
    【leetcode】1619. Mean of Array After Removing Some Elements
    【leetcode】1609. Even Odd Tree
    【leetcode】1608. Special Array With X Elements Greater Than or Equal X
    【leetcode】1603. Design Parking System
    【leetcode】1598. Crawler Log Folder
    Java基础加强总结(三)——代理(Proxy)Java实现Ip代理池
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/10626265.html
Copyright © 2011-2022 走看看