• [ZJOI2015]诸神眷顾的幻想乡


    传送门

    这题的字符串匹配搬到了树上……?那不在一条链咋做啊……不会了,凉凉……

    然后丽洁姐姐给我们留了一条生路……就是保证了叶子节点的个数不超过20.

    树上任意一条路径,我们总能找到一个叶子节点,使得以它为根的时候这条路径在一条链上。那我们可以把每个叶子节点作为根节点来建立广义后缀自动机,最后直接统计一下不同子串数量就行了。

    不过咋建立啊……不会了,凉凉……

    建立方法就是找树上度数为1的点,之后从SAM的根开始建立,这里有一些不同的是,我们需要返回一下当前的新节点编号,因为我们在树上遍历的时候,只知道你要插入的字符,不知道你要往哪插……然后我们就这样遍历这棵树,插入对应字符即可。

    最后统计一下不同的子串数量。因为这题是本质不同的个数,所以直接遍历所有节点,答案加上(l[i] - l[fa[i]])即可。

    看一下代码。

    #include<bits/stdc++.h>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    
    using namespace std;
    typedef long long ll;
    const int M = 100005;
    const int N = 2000005;
    const ll INF = 5e18;
    
    int read()
    {
       int ans = 0,op = 1;char ch = getchar();
       while(ch < '0' || ch > '9') {if(ch == '-') op = -1;ch = getchar();}
       while(ch >='0' && ch <= '9') ans = ans * 10 + ch - '0',ch = getchar();
       return ans * op;
    }
    
    int s[M],head[N],ecnt,n,c,x,y,deg[N];
    ll ans;
    
    struct edge
    {
        int next,to,from;
    }e[N<<1];
    
    struct Suffix
    {
        int cnt,ch[N][15],fa[N],l[N];
        int extend(int p,int c)
        {
            int np = ++cnt;
            l[np] = l[p] + 1;
            while(p && !ch[p][c]) ch[p][c] = np,p = fa[p];
            if(!p) {fa[np] = 1;return np;}
            int q = ch[p][c];
            if(l[q] == l[p] + 1) fa[np] = q;
            else
            {
                int nq = ++cnt;
                l[nq] = l[p] + 1,memcpy(ch[nq],ch[q],sizeof(ch[q]));
                fa[nq] = fa[q],fa[q] = fa[np] = nq;
                while(ch[p][c] == q) ch[p][c] = nq,p = fa[p];
            }
            return np;
        }
        void cal()
        {
            rep(i,2,cnt) ans += l[i] - l[fa[i]];
            printf("%lld
    ",ans);
        }
    }SAM;
    
    void add(int x,int y)
    {
        e[++ecnt] = (edge){head[x],y,x};
        head[x] = ecnt;
    }
    
    void dfs(int x,int fa,int g)
    {
        g = SAM.extend(g,s[x]);
        for(int i = head[x];i;i = e[i].next) if(e[i].to != fa) dfs(e[i].to,x,g);
    }
    
    int main()
    {
        n = read(),c = read(),SAM.cnt = 1;
        rep(i,1,n) s[i] = read();
        rep(i,1,n-1) x = read(),y = read(),add(x,y),add(y,x),deg[x]++,deg[y]++;
        rep(i,1,n) if(deg[i] == 1) dfs(i,0,1);
        SAM.cal();
        return 0;
    }
    
  • 相关阅读:
    poj1830 开关问题
    poj1681 Painter's Problem
    poj1222 EXTENDED LIGHTS OUT
    bzoj1923 [Sdoi2010]外星千足虫
    bzoj1013 [JSOI2008]球形空间产生器sphere
    poj2888 Magic Bracelet
    poj2409 Let it Bead
    poj1286 Necklace of Beads
    bzoj1004 HNOI2008 Cards
    bzoj2040 [2009国家集训队]拯救Protoss的故乡
  • 原文地址:https://www.cnblogs.com/captain1/p/10261252.html
Copyright © 2020-2023  润新知