可以说也是很迷了。最近写的字符串的题都很迷。。
首先看到路牌先写板子AC机,然后迷
然后???
回忆一下fail的定义:fail[i]到根形成的字符串是i到根形成的字符串的后缀。
那么大力跳fail硬搞
那么题目询问就变成了求在第y个字符串的那条路径上,有多少个节点fail指向的是第x个字符串的最后一个节点。
根据题解考虑离线搞。
排序一下,这样我们就可以把询问相同y字符串放在一起做。
还是不会做。先把后缀树建出来吧。
诶好像在底部的点都可以对上层的点作出贡献诶,也就是说假如y中的一个点的fail指向x的结尾,那么这个点肯定在x的结尾点的子树里面,那是不是dfs序一下搞个树状数组求答案就行了?
那就再for一次原串,遇到字符就给它+1,删就-1,到了P就看下现在是第几个字符串,这个时候的树状数组就已经把当前字符串的值记录下来了,找到所对应的询问的x串结尾在哪,把它子树的值求出来就行了。
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; char ss[110000];int slen; int cnt,chuan[110000]; struct Trie { int w[30],fa,fail; }tr[510000];int trlen; void insert() { scanf("%s",ss+1);slen=strlen(ss+1); trlen=0;cnt=0; int now=0; for(int i=1;i<=slen;i++) { if(ss[i]==‘B‘)now=tr[now].fa; else if(ss[i]==‘P‘)chuan[++cnt]=now; else { int x=ss[i]-‘a‘+1; if(tr[now].w[x]==0) tr[now].w[x]=++trlen, tr[trlen].fa=now; now=tr[now].w[x]; } } } int list[510000]; void bfs() { int head=1,tail=2;list[head]=0; while(head!=tail) { int now=list[head]; for(int x=1;x<=26;x++) { int son=tr[now].w[x]; if(son!=0) { if(now==0)tr[son].fail=0; else { int p=tr[now].fail; while(p!=0&&tr[p].w[x]==0)p=tr[p].fail; tr[son].fail=tr[p].w[x]; } list[tail]=son; tail++;if(tail==505000)tail=1; } } head++;if(head==505000)head=1; } } //-----------------AC_machine------------------------ struct node { int x,y,next; }a[510000];int len,last[510000]; void ins(int x,int y) { len++; a[len].x=x;a[len].y=y; a[len].next=last[x];last[x]=len; } int z,l[510000],r[510000]; void get_dfs(int x) { l[x]=++z; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; get_dfs(y); } r[x]=z; } void makefailtree() { len=0;memset(last,0,sizeof(last)); for(int i=1;i<=trlen;i++)ins(tr[i].fail,i); z=0;get_dfs(0); } //-------------make tree and get dfs--------------------- int s[510000]; int lowbit(int x){return x&-x;} void change(int x,int k) { while(x<=z) { s[x]+=k; x+=lowbit(x); } } int getsum(int x) { int ret=0; while(x>=1) { ret+=s[x]; x-=lowbit(x); } return ret; } //--------------bit----------------------- struct query { int x,y,id; }q[110000];int tip; bool cmp(query n1,query n2){return n1.y<n2.y;} int as[110000]; int main() { freopen("type.in","r",stdin); freopen("type.out","w",stdout); insert();bfs(); makefailtree(); int Q; scanf("%d",&Q); for(int 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); tip=1;int p=0,num=0; for(int i=1;i<=slen;i++) { if(ss[i]==‘P‘) { num++; while(q[tip].y==num) { int u=chuan[q[tip].x]; as[q[tip].id]=getsum(r[u])-getsum(l[u]-1); tip++; } } else if(ss[i]==‘B‘) change(l[p],-1),p=tr[p].fa; else p=tr[p].w[ss[i]-‘a‘+1],change(l[p],1); } for(int i=1;i<=Q;i++)printf("%d\n",as[i]); return 0; }