p2414 [NOI2011]阿狸的打字机
分析
坑点就是没有本质相同的字符串且x<=y
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
char s[200100];
int n,m,trie[200100][26],fail[200100],fa[200100],cnt;
int Trie[200100][26],bel[200100],a[200100],ans[200100];
int dfn[200100],fin[200100],tot,le[200100],ri[200100];
int head[400100],nxt[400100],to[400100],S;
inline void ADD(int x,int y){
nxt[++S]=head[x];
head[x]=S;
to[S]=y;
nxt[++S]=head[y];
head[y]=S;
to[S]=x;
}
struct node {
int x,y,id;
};
node q[200100];
vector<int>v[200100];
inline void build(){
int i,j,k,p=0;
k=strlen(s);
for(i=0;i<k;i++)
if(islower(s[i])){
if(!trie[p][s[i]-'a']){
trie[p][s[i]-'a']=++cnt;
fa[cnt]=p;
}
p=trie[p][s[i]-'a'];
}else if(s[i]=='B')p=fa[p];
else a[++n]=p,bel[p]=n;
}
queue<int>qq;
inline void getfail(){
int i,j,k;
for(i=0;i<26;i++)
if(trie[0][i]){
fail[trie[0][i]]=0;
qq.push(trie[0][i]);
}
while(!qq.empty()){
int p=qq.front();
qq.pop();
for(i=0;i<26;i++)
if(trie[p][i]){
fail[trie[p][i]]=trie[fail[p]][i];
qq.push(trie[p][i]);
}else trie[p][i]=trie[fail[p]][i];
}
}
inline void dfs(int x){
dfn[x]=++tot;
for(int i=head[x];i;i=nxt[i])
if(!dfn[to[i]])dfs(to[i]);
fin[x]=tot;
}
inline bool cmp(const node x,const node y){
return x.y<y.y;
}
int d[200100];
inline int lb(int x){return x&(-x);}
inline void add(int x,int k){while(x<=tot)d[x]+=k,x+=lb(x);}
inline int que(int x){int res=0;while(x)res+=d[x],x-=lb(x);return res;}
inline void work(int x){
add(dfn[x],1);
if(bel[x]){
for(int i=le[bel[x]];i<=ri[bel[x]];i++)
ans[q[i].id]=que(fin[a[q[i].x]])-que(dfn[a[q[i].x]]-1);
}
for(int i=0;i<26;i++)
if(Trie[x][i])work(Trie[x][i]);
add(dfn[x],-1);
}
int main(){
int i,j,k,Q;
scanf("%s",s);
build();
for(i=0;i<=cnt;i++)
for(j=0;j<26;j++)
Trie[i][j]=trie[i][j];
getfail();
for(i=1;i<=cnt;i++)ADD(fail[i],i);
dfs(0);
scanf("%d",&Q);
for(i=1;i<=Q;i++)scanf("%d%d",&q[i].x,&q[i].y),q[i].id=i;
sort(q+1,q+Q+1,cmp);
for(i=1,k=1;i<=Q;i=k){
le[q[i].y]=i;
while(q[k].y==q[i].y)k++;
ri[q[i].y]=k-1;
}
work(0);
for(i=1;i<=Q;i++)printf("%d\n",ans[i]);
return 0;
}