• BZOJ3881 Coci2015Divljak(AC自动机+树上差分+树状数组)


      建出AC自动机及其fail树,每次给新加入的串在AC自动机上经过的点染色,问题即转化为子树颜色数。显然可以用dfs序转成序列问题树状数组套权值线段树解决,显然过不掉。事实上直接树上差分,按dfs序排序后lca处-1,树状数组维护子树和即可。

      又一次写了cmp后没放进sort,心态爆炸。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define N 2000010
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    int n,m,trie[N][26],fail[N],val[N],id[N],q[N],tree[N],end[N],tmp[N],cnt;
    char s[N];
    void add(int k,int x){while (k<=cnt) tree[k]+=x,k+=k&-k;}
    int query(int k){int s=0;while (k) s+=tree[k],k-=k&-k;return s;}
    namespace Tree
    {
        int p[N],t,dfn[N],size[N],fa[N][22],deep[N],cnt;
        struct data{int to,nxt;}edge[N];
        void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
        void dfs(int k)
        {
            dfn[k]=++cnt;size[k]=1;
            for (int i=p[k];i;i=edge[i].nxt)
            {
                deep[edge[i].to]=deep[k]+1;
                fa[edge[i].to][0]=k;
                dfs(edge[i].to);
                size[k]+=size[edge[i].to];
            }
        }
        void build()
        {
            cnt=0;dfs(0);
            for (int j=1;j<22;j++)
                for (int i=0;i<cnt;i++)
                fa[i][j]=fa[fa[i][j-1]][j-1];
        }
        int lca(int x,int y)
        {
            if (deep[x]<deep[y]) swap(x,y);
            for (int j=21;~j;j--) if (deep[fa[x][j]]>=deep[y]) x=fa[x][j];
            if (x==y) return x;
            for (int j=21;~j;j--) if (fa[x][j]!=fa[y][j]) x=fa[x][j],y=fa[y][j];
            return fa[x][0];
        }
    }
    void ins(char *s,int n,int p)
    {
        int k=0;
        for (int i=1;i<=n;i++)
        {
            if (!trie[k][s[i]-'a']) trie[k][s[i]-'a']=++cnt;
            k=trie[k][s[i]-'a'];
        }
        end[p]=k;
    }
    void build()
    {
        int head=0,tail=0;for (int i=0;i<26;i++) if (trie[0][i]) q[++tail]=trie[0][i],Tree::addedge(0,trie[0][i]);
        do
        {
            int x=q[++head];
            for (int i=0;i<26;i++)
            if (trie[x][i]) fail[trie[x][i]]=trie[fail[x]][i],Tree::addedge(fail[trie[x][i]],trie[x][i]),q[++tail]=trie[x][i];
            else trie[x][i]=trie[fail[x]][i];
        }while (head<tail);
        Tree::build();
    }
    bool cmp(const int&a,const int&b)
    {
        return Tree::dfn[a]<Tree::dfn[b];
    }
    void run(char *a,int n)
    {
        int k=0,cnt=0;tmp[++cnt]=0;
        for (int i=1;i<=n;i++) tmp[++cnt]=k=trie[k][a[i]-'a'];
        sort(tmp+1,tmp+cnt+1,cmp);
        for (int i=1;i<=cnt;i++) add(Tree::dfn[tmp[i]],1);
        for (int i=2;i<=cnt;i++) add(Tree::dfn[Tree::lca(tmp[i-1],tmp[i])],-1);
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj3881.in","r",stdin);
        freopen("bzoj3881.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        m=read();
        for (int i=1;i<=m;i++)
        {
            scanf("%s",s+1);n=strlen(s+1);
            ins(s,n,i);
        }
        build();cnt++;
        m=read();
        while (m--)
        {
            int op=read();
            if (op==1)
            {
                scanf("%s",s+1);n=strlen(s+1);
                run(s,n);
            }
            else
            {
                int x=read();
                printf("%d
    ",query(Tree::dfn[end[x]]+Tree::size[end[x]]-1)-query(Tree::dfn[end[x]]-1));
            }
        }
        return 0;
    }
  • 相关阅读:
    开发中的一些总结。。。
    Directory Listing Denied错误
    webservice的一些使用心得。。
    vs2005 sp1 补丁后,不能初始化
    谈C/C++指针精髓
    CString 的函数
    javaScript 中 call 函数的用法说明 & 继承
    条款12: 尽量使用初始化而不要在构造函数里赋值(effectiveC++)
    js日期时间函数(经典+完善+实用)
    学习之路一 记录学习中的手记
  • 原文地址:https://www.cnblogs.com/Gloid/p/10208114.html
Copyright © 2020-2023  润新知