zoukankan      html  css  js  c++  java
  • bzoj4545

    lct+SAM

    bzoj4516+bzoj2555

    这道题唯一的用处就是教会了我真正的广义SAM

    dfs时保留当前节点在后缀自动机中的位置,每个点接着父亲建

    lct动态维护right集合大小,用lct维护子树就行了

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int N = 1e5 + 5;
    struct edge {
        int nxt, to, w;
    } e[N << 1];
    int n, m, cnt = 1;
    int h[N], pos[N];
    char s[N];
    long long sum;
    namespace lct 
    {
        struct node {
            int ch[2];
            int f, tag, reg;
        } t[N << 1];
        bool isr(int x) {
            return !t[x].f || (t[t[x].f].ch[0] != x && t[t[x].f].ch[1] != x);
        }
        int wh(int x) {
            return x == t[t[x].f].ch[1];
        }
        void paint(int x, int d) {
            t[x].tag += d;
            t[x].reg += d;
        }
        void pushdown(int x) {
            if(t[x].tag) {
                paint(t[x].ch[0], t[x].tag);
                paint(t[x].ch[1], t[x].tag);
                t[x].tag = 0;
            }
        }
        void pd(int x) {
            if(!isr(x)) {
                pd(t[x].f);
            }        
            pushdown(x);
        }
        void rotate(int x) {
            int y = t[x].f, z = t[y].f, w = wh(x);
            if(!isr(y)) {
                t[z].ch[wh(y)] = x;
            }
            t[x].f = z;
            t[y].ch[w] = t[x].ch[w ^ 1];
            t[t[x].ch[w ^ 1]].f = y;
            t[y].f = x;
            t[x].ch[w ^ 1] = y;
        }
        void splay(int x) {
            pd(x);
            for(; !isr(x); rotate(x)) {
                if(!isr(t[x].f)) {
                    rotate(wh(t[x].f) == wh(x) ? t[x].f : x); 
                }
            }
        }
        void access(int x) {
            for(int y = 0; x; y = x, x = t[x].f) {
                splay(x);
                t[x].ch[1] = y;
            }
        }
        void link(int u, int v) {
            access(u);
            splay(u);
            access(v);
            splay(v);
            paint(v, t[u].reg);
            t[u].f = v;
        }
        void cut(int u, int v) {
            access(u);
            splay(u);
            t[u].ch[0] = 0;
            t[v].f = 0;
            paint(v, -t[u].reg);
        }
    }
    namespace SAM 
    {
        struct node {
            int ch[26];
            int par, val;
        } t[N << 1];
        int root = 1, sz = 1;
        int nw(int x) {
            t[++sz].val = x;
            return sz;
        }
        int extend(int last, int c) {
            int p = last, np = nw(t[p].val + 1);
            lct::t[np].reg = 1;
            while(p && !t[p].ch[c]) {
                t[p].ch[c] = np;
                p = t[p].par;
            }
            if(!p) {
                t[np].par = root;
                lct::link(np, root);
            } else {
                int q = t[p].ch[c];
                if(t[q].val == t[p].val + 1) {
                    t[np].par = q;
                    lct::link(np, q);
                } else {
                    int nq = nw(t[p].val + 1);
                    lct::link(nq, t[q].par); 
                    lct::cut(q, t[q].par);
                    lct::link(np, nq);
                    lct::link(q, nq);
                    t[nq].par = t[q].par;
                    t[np].par = t[q].par = nq;
                    memcpy(t[nq].ch, t[q].ch, sizeof(t[q].ch));
                    while(p && t[p].ch[c] == q) {
                        t[p].ch[c] = nq;
                        p = t[p].par;
                    }
                }
            }
            sum += t[np].val - t[t[np].par].val;
            return np;
        }
        void solve(char *s) {
            int len = strlen(s), now = root;
            for(int i = 0; i < len; ++i) {
                if(!t[now].ch[s[i] - 'a']) {
                    puts("0");
                    return;
                }
                now = t[now].ch[s[i] - 'a'];
            }
            lct::pd(now);
            printf("%d
    ", lct::t[now].reg);
            lct::splay(now);
        }
    }
    void link(int u, int v, int w) {
        e[++cnt].nxt = h[u];
        h[u] = cnt;
        e[cnt].to = v;
        e[cnt].w = w;
    }
    void dfs(int u, int last) {
        for(int i = h[u]; i; i = e[i].nxt) {
            if(e[i].to == last) {
                continue;
            }
            pos[e[i].to] = SAM::extend(pos[u], e[i].w);
            dfs(e[i].to, u);
        }
        h[u] = 0;
    }
    int main() {
    //    freopen("1.out", "w", stdout);
        int laji;
        scanf("%d%d", &laji, &n);
        for(int i = 1; i < n; ++i) {
            int u, v;
            scanf("%d%d%s", &u, &v, s);
            link(u, v, s[0] - 'a');
            link(v, u, s[0] - 'a');
        }
        pos[1] = 1;
        dfs(1, 0);
        scanf("%d", &m);
        while(m--) {
            int opt;
            scanf("%d", &opt);
            if(opt == 1) {
                printf("%lld
    ", sum);
            } else if(opt == 2) {
                int rt, sz;
                scanf("%d%d", &rt, &sz);
                while(--sz) {
                    int u, v;
                    scanf("%d%d%s", &u, &v, s);
                    link(u, v, s[0] - 'a');
                    link(v, u, s[0] - 'a');
                }
                dfs(rt, 0);
            } else {
                scanf("%s", s);
                SAM::solve(s);
            }
        }
        return 0;
    } 
    View Code
  • 相关阅读:
    对话框事件
    C# 实现retry
    Linq中的group by多表多字段,Sum求和
    词干提取(stemming)和词形还原(lemmatization)
    GIT简单应用实例
    像素、分辨率、dpi的区别和联系
    二值图像、灰度图像、彩色图像
    更好的做科研
    数据挖掘竞赛利器-Stacking和Blending方式
    如何成为一名成功的博士生
  • 原文地址:https://www.cnblogs.com/19992147orz/p/8486774.html
Copyright © 2011-2022 走看看