SPOJ 8093 JZPGYZ

思路

可以用复杂度不对的做法水过去
相当于求parent树子树中的颜色种数,可以离线后树状数组(HH的项链,询问右端点排序之后维护last),dsu on tree,莫队都可以
但是也可以记录每个点上次被更新的原串(last[i]),然后通过fail向上更新

代码

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <bits/stdc++.h>
using namespace std;
int Nodecnt=1,trans[200000][26],suflink[200000],sz[200000],last[200000],maxlen[200000],n,m;
char s[200000];
int New_state(int _maxlen,int _sz,int *_trans,int _suflink,int _last){
    ++Nodecnt;
    sz[Nodecnt]=_sz;
    if(_trans)
        for(int i=0;i<26;i++)
            trans[Nodecnt][i]=_trans[i];
    suflink[Nodecnt]=_suflink;
    last[Nodecnt]=_last;
    maxlen[Nodecnt]=_maxlen;
    return Nodecnt;
}
inline void update(int u,int x){
    while(u&&last[u]!=x){
        sz[u]++;
        last[u]=x;
        u=suflink[u];
    }
}
int add_len(int u,int c,int inq){
    if(trans[u][c]){
        int v=trans[u][c];
        if(maxlen[v]==maxlen[u]+1){
            update(v,inq);
            return v;
        }
        int y=New_state(maxlen[u]+1,sz[v],trans[v],suflink[v],last[v]);
        suflink[v]=y;
        while(u&&trans[u][c]==v){
            trans[u][c]=y;
            u=suflink[u];
        }
        update(y,inq);
        return y;
    }
    else{
        int z=New_state(maxlen[u]+1,0,NULL,0,0);
        while(u&&trans[u][c]==0){
            trans[u][c]=z;
            u=suflink[u];
        }
        if(!u){
            suflink[z]=1;
            update(z,inq);
            return z;
        }
        int v=trans[u][c];
        if(maxlen[v]==maxlen[u]+1){
            suflink[z]=v;
            update(z,inq);
            return z;
        }
        int y=New_state(maxlen[u]+1,sz[v],trans[v],suflink[v],last[v]);
        suflink[v]=suflink[z]=y;
        while(u&&trans[u][c]==v){
            trans[u][c]=y;
            u=suflink[u];
        }
        update(z,inq);
        return z;
    }
}
int query(char *s,int len){
    int o=1;
    for(int i=1;i<=len;i++){
        o=trans[o][s[i]-'a'];
    }
    return sz[o];
}
int main(){
    freopen("test.in","r",stdin);
    freopen("test.out","w",stdout);
    scanf("%d %d",&n,&m);
    Nodecnt=1;
    for(int i=1;i<=n;i++){
        scanf("%s",s+1);
        int len=strlen(s+1),last=1;
        for(int j=1;j<=len;j++)
            last=add_len(last,s[j]-'a',i);
    }
    sz[0]=0;
    for(int i=1;i<=m;i++){
        scanf("%s",s+1);
        int len=strlen(s+1);
        printf("%d
",query(s,len));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/dreagonm/p/10717958.html