• luogu SP8093 后缀自动机+树状数组+dfs序


    这题解法很多,简单说几个:

    1. 线段树合并,时间复杂度是 $O(nlog^2n)$ 的. 

    2. 暴力跳 $fail,$ 时间复杂度 $O(nsqrt n),$ 比较暴力. 

    3. 建立后缀树后在 $dfs$ 序上数点,时间复杂度为 $O(nlogn),$ 十分优秀. 

    Code: 

    #include <bits/stdc++.h>  
    #define N 200007    
    #define setIO(s) freopen(s".in","r",stdin) , freopen(s".out","w",stdout)    
    using namespace std;          
    struct ques
    { 
        int l,r,id;  
        ques(int l=0,int r=0,int id=0):l(l),r(r),id(id){}    
    }q[N];  
    struct P 
    { 
        int len,f,ch[27];
        vector<int>v;     
    }t[N<<1];     
    char S[N];
    vector<int>G[N];        
    int tot,last,edges,tim,cnt;     
    int hd[N],to[N],nex[N],st[N],ed[N],size[N],dfn[N],lst[N],C[N],answer[N];      
    int lowbit(int t) 
    {
        return t&(-t); 
    }    
    void update(int x,int delta) 
    {
        for(;x<N;x+=lowbit(x)) C[x]+=delta;  
    }
    int query(int x) 
    {
        int tmp=0; 
        for(;x>0;x-=lowbit(x)) tmp+=C[x];  
        return tmp;     
    }
    bool cmp(ques a,ques b) 
    {
        return a.r<b.r;     
    }    
    void addedge(int u,int v) 
    {
        nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;     
    }
    void extend(int c,int id) 
    {  
        if(t[last].ch[c]) 
        { 
            int p=last;  
            int q=t[p].ch[c];       
            if(t[q].len==t[p].len+1) last=q;   
            else
            {
                int nq=++tot; 
                t[nq].len=t[p].len+1;    
                t[nq].f=t[q].f,t[q].f=nq;   
                memcpy(t[nq].ch, t[q].ch, sizeof(t[q].ch));    
                for(;p&&t[p].ch[c]==q;p=t[p].f) t[p].ch[c]=nq;   
                last=nq;     
            }
        }
        else 
        {
            int np=++tot,p=last;  
            t[np].len=t[p].len+1,last=np;  
            for(;p&&!t[p].ch[c];p=t[p].f) t[p].ch[c]=np;   
            if(!p) t[np].f=1;  
            else 
            {
                int q=t[p].ch[c];  
                if(t[q].len==t[p].len+1) t[np].f=q;  
                else
                {
                    int nq=++tot; 
                    t[nq].len=t[p].len+1;    
                    t[nq].f=t[q].f,t[q].f=t[np].f=nq;   
                    memcpy(t[nq].ch, t[q].ch, sizeof(t[q].ch));    
                    for(;p&&t[p].ch[c]==q;p=t[p].f) t[p].ch[c]=nq;   
                }
            }
        }
        t[last].v.push_back(id);     
    }
    void dfs(int u) 
    {           
        dfn[u]=st[u]=++tim; 
        for(int i=hd[u];i;i=nex[i]) 
        {
            int v=to[i];   
            dfs(v);                       
        }    
        for(int k=0;k<t[u].v.size();++k) 
            G[dfn[u]].push_back(t[u].v[k]);   
        ed[u]=tim;    
    }
    int main() 
    {   
        last=tot=1; 
        int i,j,n,m,k;      
        // setIO("input");                       
        scanf("%d%d",&n,&m);    
        for(i=1;i<=n;++i) 
        { 
            last=1;   
            scanf("%s",S+1);    
            int len=strlen(S+1);   
            for(j=1;j<=len;++j) extend(S[j]-'a',i);   
        }   
        for(i=2;i<=tot;++i) 
            addedge(t[i].f,i);   
        dfs(1);              
        for(i=1;i<=m;++i) 
        {
            scanf("%s",S+1);  
            int len=strlen(S+1),p=1;   
            for(j=1;j<=len;++j) 
            {
                int c=S[j]-'a';   
                if(!t[p].ch[c]) 
                {
                    p=-1;   
                    break;   
                } 
                else p=t[p].ch[c];      
            }
            if(p!=-1) q[++cnt]=ques(st[p],ed[p],i);        
        }    
        sort(q+1,q+1+cnt,cmp);              
        for(j=i=1;i<=cnt;++i) 
        {
            for(;j<=q[i].r;++j) 
            {    
                for(k=0;k<G[j].size();++k) 
                {  
                    int tt=G[j][k];   
                    if(lst[tt]) update(lst[tt],-1);  
                    lst[tt]=j;    
                    update(j,1);   
                }
            }
            answer[q[i].id]=query(q[i].r)-query(q[i].l-1);     
        }
        for(i=1;i<=m;++i) printf("%d
    ",answer[i]);   
        return 0; 
    } 
    

      

  • 相关阅读:
    电脑能ping127.0.0.1但是ping不通本机ip
    用iis调试源代码
    pl登录提示服务不存在
    sqlserver保留一位小数(不是四舍五入)
    web应用程序与web网站发布时区别
    java的覆盖重写隐藏和C#中的不同
    导出word
    点击登录提交两次的问题
    oracle通过plsql代码倒库
    apply方法自解
  • 原文地址:https://www.cnblogs.com/guangheli/p/11577267.html
Copyright © 2020-2023  润新知