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

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

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

2. 暴力跳 $fail,$ 时间复杂度 $O(n\sqrt 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\n",answer[i]);   
    return 0; 
} 

  

posted @ 2019-09-24 11:15  EM-LGH  阅读(177)  评论(0编辑  收藏  举报