【BZOJ2434】【NOI2011】—阿狸的打字机(AC自动机+线段树)
考虑一个串在另一个串中出现的次数
其实就是串的链上有多少个点的直接或间接指向的末指针
所以建出树后就是的末指针的子树和
每次暴力把的所有点设成1查询可以有分
离线后对于每个记一下要询问哪些就行了
复杂度
#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define gc getchar
inline int read(){
int res=0,f=1;
char ch=gc();
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
const int N=100005;
char op[N];
int n,m;
namespace Ac{
struct node{
int nxt[27],fail,fa;
vector<int> e;
vector<int> id;
}t[N];
struct ask{
int x,y,id;
friend inline bool operator <(const ask &a,const ask &b){
return a.y<b.y;
}
}q[N];
vector<int> e[N];
int in[N],out[N],dfn,tot,ql[N],qr[N],ed[N],ans[N];
int tr[N];
#define lb(x) (x&(-x))
inline void update(int p,int k){
for(;p<=dfn;p+=lb(p))tr[p]+=k;
}
inline int query(int p,int res=0){
for(;p;p-=lb(p))res+=tr[p];return res;
}
inline void buildfail(){
queue<int> q;
for(int i=0;i<26;i++)
if(t[0].nxt[i])q.push(t[0].nxt[i]);
while(!q.empty()){
int u=q.front();q.pop();
for(int i=0;i<26;i++){
int v=t[u].nxt[i];
if(v)t[v].fail=t[t[u].fail].nxt[i],q.push(v);
else t[u].nxt[i]=t[t[u].fail].nxt[i];
}
}
}
void dfs1(int u){
in[u]=++dfn;
for(int i=0;i<e[u].size();i++){
dfs1(e[u][i]);
}
out[u]=dfn;
}
void dfs2(int u){
update(in[u],1);
if(t[u].id.size()){
for(int j=0;j<t[u].id.size();j++){
int p=t[u].id[j];
for(int i=ql[p];i<=qr[p];i++){
ans[q[i].id]=query(out[ed[q[i].x]])-query(in[ed[q[i].x]]-1);
}
}
}
for(int i=0;i<t[u].e.size();i++){
int v=t[u].e[i];
dfs2(v);
}
update(in[u],-1);
}
}
using namespace Ac;
int main(){
scanf("%s",op+1);
int now=0;
for(int i=1,len=strlen(op+1);i<=len;i++){
if(op[i]>='a'&&op[i]<='z'){
if(!t[now].nxt[op[i]-'a'])t[now].nxt[op[i]-'a']=++tot,t[tot].fa=now;
now=t[now].nxt[op[i]-'a'];
}
if(op[i]=='B')now=t[now].fa;
if(op[i]=='P')ed[++n]=now,t[now].id.pb(n);
}
for(int i=0;i<=tot;i++)
for(int j=0;j<26;j++)if(t[i].nxt[j])t[i].e.pb(t[i].nxt[j]);
buildfail();
for(int i=1;i<=tot;i++)e[t[i].fail].pb(i);
dfs1(0);
m=read();
for(int i=1;i<=m;i++)
q[i].x=read(),q[i].y=read(),q[i].id=i;
sort(q+1,q+m+1);
for(int i=1,pos=1;i<=m;i=pos){
ql[q[i].y]=i;
while(q[pos].y==q[i].y)pos++;
qr[q[i].y]=pos-1;
}
dfs2(0);
for(int i=1;i<=m;i++)cout<<ans[i]<<'\n';
}