zoukankan      html  css  js  c++  java
  • BZOJ 3926: [Zjoi20150]诸神眷顾的幻想乡(后缀自动机)

    被这道题坑了= =
    只与一个空地相连的空地不超过20个
    只与一个空地相连的空地不超过20个

    因为很重要所以说两遍

    就是说儿子节点最多只有20个

    把这20个节点作为根遍历一遍所得到的tire所得到的所有不同子串就是答案了

    怎么求?

    这可是CLJ出的啊

    想想她讲过什么

    后缀自动机或可持久化后缀数组的经典应用

    由于不会打可持久化后缀数组,就打了个自动机

    自己对后缀自动机根本不熟,找时间在多做几道题

    CODE:

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    using namespace std;
    struct node{
        node* c[12];int id;
        node(){memset(c,0,sizeof(c));}
    };
    #define maxn 101000
    vector<int> e[maxn];
    #define pb push_back
    int a[maxn],pre[maxn];
    inline void bfs(int x,node *&y){
        if (!y) y=new node;
        static int q[maxn];
        static node * p[maxn];
        q[1]=x;
        p[1]=y;
        pre[x]=0;
        for (int l=1,r=1,u=q[1];l<=r;u=q[++l]) {
            for (vector<int>::iterator i=e[u].begin();i!=e[u].end();++i) {
                if (*i==pre[u]) continue;
                pre[*i]=u;q[++r]=*i;
                if (!p[l]->c[a[*i]]) p[l]->c[a[*i]]=new node;
                p[r]=p[l]->c[a[*i]];
            }
        }
    }
    struct snode{int ch[13],l,fa;}s[maxn*50];
    typedef long long ll;
    int cnt;ll ans;
    inline void add(int x,node* u) {
        int p=++cnt,t=u->id;
        u->c[x]->id=p;
        s[p].l=s[t].l+1;
        for (;t!=-1&&!s[t].ch[x];t=s[t].fa) s[t].ch[x]=p;
        if (t==-1) s[p].fa=0;
        else if (s[t].l+1==s[s[t].ch[x]].l) s[p].fa=s[t].ch[x];
        else {
            int r=++cnt,q=s[t].ch[x];
            s[r]=s[q];s[r].l=s[t].l+1;
            s[p].fa=s[q].fa=r;
            for (;t!=-1&&s[t].ch[x]==q;t=s[t].fa) s[t].ch[x]=r;
        }
        ans+=s[p].l-s[s[p].fa].l;
    }
    int c;
    node *root;
    inline void build(){
        static node *q[maxn*50];
        q[1]=root;
        root->id=0;
        s[0].fa=-1;
        for (int l=1,r=1;l<=r;l++) {
            node *u=q[l];
            for (int i=0;i<=c;i++) 
                if (u->c[i]) {
                    add(i,u);
                    q[++r]=u->c[i];
                }
        }
    }
    int main(){
        int n;
        scanf("%d%d",&n,&c);
        for (int i=1;i<=n;i++) scanf("%d",a+i);
        for (int i=1;i<=n;i++) a[i]++;
        root=new node;
        for (int i=1;i<n;i++) {
            int x,y;
            scanf("%d%d",&x,&y);
            e[x].pb(y);e[y].pb(x);
        }
        for (int i=1;i<=n;i++) if (e[i].size()==1) bfs(i,root->c[a[i]]);
        build();
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    Python 基础语法学习 1 -- Print
    Using CMD to create Android automation environment
    Java学习随笔之9:AWT编程
    Java学习随笔之8: 异常处理
    Android自动化测试2:Demo code
    Android自动化测试1:环境准备
    Java学习随笔之7:java 集合
    Java学习随笔之6:基本类库
    Java学习随笔之5: 面向对象(下)
    Java学习随笔之4:面向对象(上)
  • 原文地址:https://www.cnblogs.com/New-Godess/p/4420888.html
Copyright © 2011-2022 走看看