http://www.lydsy.com/JudgeOnline/problem.php?id=2434
AC自动机。
首先第1行的输入就是让我们建AC自动机。。。。。。(提示好大)
记第i个字符串在AC自动机里面的点编号为pos[i]。
其实询问就是:对于在AC自动机里pos[y]到根的路径上的所有结点,有多少个在fail-tree中在以pos[x]为根的子树中。
我们可以先在fail-tree中DFS,求出每个点i的DFS序idx[i],子树中最小的DFS序l[i]和子树中最大DFS序r[i],并建立树状数组。
然后在AC自动机里DFS,访问点i就在idx[i]位置+1,离开点i就在idx[i]位置-1,这样就是维护了点i到根的路径上的所有结点。
然后在树状数组里询问即可。
#include<cstdio> #include<cstdlib> #include<iostream> #include<fstream> #include<algorithm> #include<cstring> #include<string> #include<cmath> #include<queue> #include<stack> #include<map> #include<utility> #include<set> #include<bitset> #include<vector> #include<functional> #include<deque> #include<cctype> #include<climits> #include<complex> //#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj using namespace std; typedef long long LL; typedef double DB; typedef pair<int,int> PII; typedef complex<DB> CP; #define mmst(a,v) memset(a,v,sizeof(a)) #define mmcy(a,b) memcpy(a,b,sizeof(a)) #define re(i,a,b) for(i=a;i<=b;i++) #define red(i,a,b) for(i=a;i>=b;i--) #define fi first #define se second #define m_p(a,b) make_pair(a,b) #define SF scanf #define PF printf #define two(k) (1<<(k)) template<class T>inline T sqr(T x){return x*x;} template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;} template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} const DB EPS=1e-9; inline int sgn(DB x){if(abs(x)<EPS)return 0;return(x>0)?1:-1;} const DB Pi=acos(-1.0); inline int gint() { int res=0;bool neg=0;char z; for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar()); if(z==EOF)return 0; if(z=='-'){neg=1;z=getchar();} for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar()); return (neg)?-res:res; } inline LL gll() { LL res=0;bool neg=0;char z; for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar()); if(z==EOF)return 0; if(z=='-'){neg=1;z=getchar();} for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar()); return (neg)?-res:res; } const int maxN=100000; const int maxM=100000; const int maxlen=100000; int N,M; char s[maxlen+100]; int pos[maxN+100]; int now,first[maxlen+100]; struct Tedge{int v,next;}edge[maxlen+100]; inline void addedge(int u,int v) { now++; edge[now].v=v; edge[now].next=first[u]; first[u]=now; } int cnt,fa[maxlen+100],fail[maxlen+100],ch[maxlen+100][30]; int head,tail,que[maxlen+100]; inline void build() { int i,p; cnt=p=1; fa[1]=0; int len=strlen(s+1); re(i,1,len) if(s[i]=='B') p=fa[p]; else if(s[i]=='P') pos[++N]=p; else { if(!ch[p][s[i]-'a'])ch[p][s[i]-'a']=++cnt,fa[cnt]=p; p=ch[p][s[i]-'a']; } mmst(first,-1);now=-1; fail[que[head=tail=1]=1]=1; while(head<=tail) { int u=que[head++]; re(i,0,25)if(ch[u][i]) { int v=ch[u][i]; if(u==1) fail[que[++tail]=v]=1; else { int temp=fail[u]; while(temp!=1 && !ch[temp][i])temp=fail[temp]; if(ch[temp][i])temp=ch[temp][i]; fail[que[++tail]=v]=temp; } addedge(fail[v],v); } } } int ge,idx[maxlen+100],l[maxlen+100],r[maxlen+100]; int top,sta[maxlen+100],last[maxlen+100]; inline void DFS1() { idx[sta[top=1]=1]=ge=1; last[top]=first[1]; while(top>=1) { int u=sta[top],i=last[top],v; for(v=edge[i].v;i!=-1;i=edge[i].next,v=edge[i].v) { idx[sta[++top]=v]=++ge; last[top]=first[v]; last[top-1]=edge[i].next; break; } if(i==-1) { l[u]=r[u]=idx[u]; for(i=first[u],v=edge[i].v;i!=-1;i=edge[i].next,v=edge[i].v)upmin(l[u],l[v]),upmax(r[u],r[v]); top--; } } } #define lowbit(a) ((a)&(-(a))) int tree[maxlen+100]; inline void update(int a,int v){for(;a<=cnt;a+=lowbit(a))tree[a]+=v;} inline int ask(int l,int r) { int res=0; for(;r>=1;r-=lowbit(r))res+=tree[r]; for(l--;l>=1;l-=lowbit(l))res-=tree[l]; return res; } vector<PII> Q[maxlen+100]; int ans[maxM+100]; inline void DFS2() { sta[top=1]=1; last[top]=0; while(top>=1) { int u=sta[top],i=last[top],v,j; for(v=ch[u][i];i<26;i++,v=ch[u][i])if(v) { sta[++top]=v; last[top]=0; last[top-1]=i+1; update(idx[v],1); re(j,0,int(Q[v].size())-1) { int x=Q[v][j].fi,w=Q[v][j].se; ans[w]=ask(l[x],r[x]); } break; } if(i==26)update(idx[u],-1),top--; } } int main() { freopen("type.in","r",stdin); freopen("type.out","w",stdout); int i; scanf("%s ",s+1); build(); M=gint(); re(i,1,M) { int x=gint(),y=gint(); Q[pos[y]].push_back(PII(pos[x],i)); } DFS1(); DFS2(); re(i,1,M)PF("%d ",ans[i]); }