zoukankan      html  css  js  c++  java
  • BZOJ 3473 字符串 ——广义后缀自动机

    这题就比较有趣了。

    首先匹配一遍,然后统计子树叶子节点中包含大于等于k的节点个数(HH的项链)

    然后就可以搞了。

    关于合法的情况数,显然是l[i]-l[fa[i]],然后向下下传即可(YY一下)。

    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
     
    #define F(i,j,k) for (int i=j;i<=k;++i)
    #define D(i,j,k) for (int i=j;i>=k;--i)
    #define ll long long
    #define maxn 600005
    struct Query{
        int l,r,id;
        void print(){printf("Query : %d to %d (id is %d)
    ",l,r,id);}
    }brr[maxn];
    bool cmp(Query a,Query b)
    {return a.l==b.l?a.r<b.r:a.l<b.l;}
    struct Bit_Tree{
        int x[maxn];
        void add(int pos,int f,int tot)
        {for (;pos<=tot;pos+=(pos&(-pos))) x[pos]+=f;}
        int query(int pos)
        {int ret=0;for(;pos;pos-=(pos&(-pos)))ret+=x[pos];return ret;}
    }BT;
    class Suffix_Automata{
        public:
        int arr[maxn],tot,top;
        int last,cnt,n,k;
        char s[maxn];
        vector <int> v[maxn],vb[maxn];
        int h[maxn],to[maxn],ne[maxn],en,in[maxn],out[maxn]; 
        int go[maxn][26],l[maxn],fa[maxn];
        void init()
        {
            last=cnt=1; en=0;
            memset(h,-1,sizeof h);
            memset(go,0,sizeof go);
        }
        void add(int x,int id)
        {
            int p=last,q;
            if (q=go[p][x])
            {
                if (l[q]==l[p]+1) last=q;
                else
                {
                    int nq=++cnt;
                    l[nq]=l[p]+1;
                    memcpy(go[nq],go[q],sizeof go[q]);
                    fa[nq]=fa[q];
                    fa[q]=nq;
                    for(;p&&go[p][x]==q;p=fa[p]) go[p][x]=nq;
                    last=nq;
                }
            }
            else
            {
                int np=++cnt; l[np]=l[p]+1;
                for (;p&&!go[p][x];p=fa[p]) go[p][x]=np;
                if (!p) fa[np]=1;
                else
                {
                    q=go[p][x];
                    if (l[q]==l[p]+1) fa[np]=q;
                    else
                    {
                        int nq=++cnt;
                        l[nq]=l[p]+1;
                        memcpy(go[nq],go[q],sizeof go[q]);
                        fa[nq]=fa[q];
                        fa[q]=fa[np]=nq;
                        for (;p&&go[p][x]==q;p=fa[p]) go[p][x]=nq;
                    }
                }
                last=np;
            }
            v[last].push_back(id);
            vb[id].push_back(last);
        }
        void addedge(int a,int b)
        {
            to[en]=b;
            ne[en]=h[a];
            h[a]=en++;
        }
        void ins(int id)
        {
            last=1;scanf("%s",s+1);
            int len=strlen(s+1);
            F(j,1,len) add(s[j]-'a',id);
        }
        void dfs(int o)
        {
            in[o]=++tot;
            for (int i=0;i<v[o].size();++i) arr[tot++]=v[o][i];
            for (int i=h[o];i>=0;i=ne[i]) dfs(to[i]);
            out[o]=tot;
            ++top;brr[top].l=in[o];brr[top].r=out[o];brr[top].id=o;
        }
        void dfs2(int o)
        {
            for (int i=h[o];i>=0;i=ne[i])
                f[to[i]]+=f[o],dfs2(to[i]);
        }
        int lst[maxn],nxt[maxn],ans[maxn],f[maxn];
        void solve()
        {
            init();
            scanf("%d%d",&n,&k);
            F(i,1,n) ins(i);
            F(i,1,cnt) addedge(fa[i],i);
            dfs(1);
    //      printf("Arr : ");F(i,1,tot) printf("%d ",arr[i]); printf("
    ");
            sort(brr+1,brr+top+1,cmp);
    //      F(i,1,top) brr[i].print();
            F(i,1,tot)
            {
                if (!lst[arr[i]]&&arr[i]) BT.add(i,1,tot);
                else nxt[lst[arr[i]]]=i;
                lst[arr[i]]=i;
            }
    //      F(i,1,tot) printf("%d ",nxt[i]); printf("
    ");
            int now=1;
            F(i,1,top)
            {
                while (now<brr[i].l)
                {
                    if (nxt[now]&&arr[nxt[now]]) BT.add(nxt[now],1,tot);
                    now++;
                }
                ans[brr[i].id]=BT.query(brr[i].r)-BT.query(brr[i].l-1);
            }
    //      F(i,1,top) printf("[%d] %d
    ",i,ans[i]);
            F(i,1,top) if (ans[i]>=k) f[i]=l[i]-l[fa[i]]; else f[i]=0;
            dfs2(1);
            F(i,1,n)
            {
                ll ans=0;
                F(j,0,vb[i].size()-1) ans+=f[vb[i][j]];
                printf("%lld",ans);
                if (i!=n) printf(" ");
            }
        }
    }sam;
     
    int main()
    {sam.solve();}
    

      

  • 相关阅读:
    Kafka常用操作备忘
    Spark执行流程(转)
    Spark性能优化总结
    Kafka学习笔记
    vue-简单例子初始化
    解析字符串模板函数
    js的apply 和 call区别
    水平垂直居中
    IE8 div旋转 Matrix,模拟轮播前后翻页按钮
    jsp 自定义标签-SimpleTagSupport 使用笔记
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6486859.html
Copyright © 2011-2022 走看看