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

Posted guangheli

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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; 
 

  

以上是关于luogu SP8093 后缀自动机+树状数组+dfs序的主要内容,如果未能解决你的问题,请参考以下文章

Spoj8093 Sevenk Love Oimaster

BZOJ2780[Spoj]8093 Sevenk Love Oimaster 广义后缀自动机

bzoj2780[Spoj]8093 Sevenk Love Oimaster 广义后缀自动机

BZOJ 2780: [Spoj]8093 Sevenk Love Oimaster [广义后缀自动机]

luogu AT2300 Snuke Line |树状数组

luogu 2617