题目(BZOJ)
题目(洛谷)
来看看这道题吧~
首先我们来想个最暴力的做法:把每个串存起来,然后暴力匹配......复杂度感人.
然后考虑加一点点优化:将这多个串放到一棵Trie上,构建AC自动机,然后像kmp那样匹配......同样感人.
我们来试试其他做法:抽离fail树。
因为在fail树上儿子节点必然可以到father结点,用树状数组维护一个dfs序即可,
具体做法就是:将询问离线,根据每个y去统计每个x,看原串:若为B,则表示退出这个结点,就把这个结点的权值-1;若为P,则表示进入这个结点,就把这个结点的权值+1。
这样就做完了,over
#include <bits/stdc++.h> using namespace std; template <class _E> inline void read(_E &e){ e=0;bool ck=0;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')ck=1;ch=getchar();} while(isdigit(ch)){e=(e<<1)+(e<<3)+(ch^48);ch=getchar();} if(ck)e=-e; } const int N=200050; int n,m; int c[N]; inline int lowbit(int x){return x&(-x);} inline void change(int x,int v){while(x<=n){c[x]+=v;x+=lowbit(x);}} inline int query(int x){int ret=0;while(x){ret+=c[x];x-=lowbit(x);}return ret;} struct querys{ int x,y,id; }q[N]; int ans[N]; inline bool cmp(const querys &x,const querys &y){ return x.y<y.y; } struct edge{ int vk,nxt; }e[N<<1]; int head[N],tt,in[N],out[N],dfn[N],tim; inline void ad(int u,int v){e[++tt].vk=v;e[tt].nxt=head[u];head[u]=tt;} inline int idx(char c){return c-'a'+1;} int now,cnt,ch[N][27],f[N],sz,val[N],fail[N],pos[N]; char s[N]; inline void charin(){ n=strlen(s);int u=0; for(int i=0;i<n;++i){ if(s[i]=='P'){pos[++cnt]=u;val[u]=1;continue;} if(s[i]=='B'){u=f[u];continue;} int c=idx(s[i]); if(!ch[u][c])ch[u][c]=++sz; f[ch[u][c]]=u;u=ch[u][c]; } } inline void buildAC(){ queue <int> q; fail[0]=0; for(int i=1;i<=26;++i){ int v=ch[0][i]; if(v)q.push(v),fail[v]=0; } while(!q.empty()){ int r=q.front();q.pop(); for(int i=1;i<=26;++i){ int u=ch[r][i]; if(!u){ch[r][i]=ch[fail[r]][i];continue;} q.push(u); int v=fail[r]; while(v&&!ch[v][i])v=fail[v]; fail[u]=ch[v][i]; val[u]|=val[fail[u]]; } } } void solve(){ int u=0,now=0,k=1; for(int i=0;i<n;++i){ switch(s[i]){ case 'P':{ for(now++;q[k].y==now&&k<=m;k++){ ans[q[k].id]=query(out[pos[q[k].x]])-query(in[pos[q[k].x]]-1); } break; } case 'B':{ change(in[u],-1); u=f[u]; break; } default:{ int c=idx(s[i]); u=ch[u][c]; change(in[u],1); break; } } } } void dfs(int u){ in[u]=++tim;dfn[tim]=u; for(int i=head[u];i;i=e[i].nxt)dfs(e[i].vk); out[u]=tim; } int main(){ scanf( read(m); for(int i=1;i<=m;++i){ read(q[i].x),read(q[i].y);q[i].id=i; } sort(q+1,q+m+1,cmp); charin();buildAC(); for(int i=1;i<=sz;++i)ad(fail[i],i); dfs(0); solve(); for(int i=1;i<=m;++i)printf( return 0; }
Comments NOTHING