[NOI2011]阿狸的打字机
[NOI2011]阿狸的打字机
题目大意:
一个老式的打字机按照如下的方式工作:用一个栈存储想要打印的内容(小写英文字母),B
键将栈顶字母出栈,P
键将栈中所有字母打印出来。
给定长度为\(n(n\le10^5)\)的操作序列(包含\(26\)个小写字母和操作B
、P
)。\(m(m\le10^5)\)次询问,第\(x\)个打印出来的字符串在第\(y\)个打印出来的字符串中出现了几次。
思路:
该打字机的特性使得我们可以很容易地构造出一个AC自动机,插入小写字母同普通的AC自动机,B
操作时直接将返回到当前结点在Trie上的父亲即可。
将原问题放到Fail树上,就是\(x\)对应的子树中有多少个结点对应着\(y\)。求出Fail树的DFS序,树状数组维护即可。
源代码:
#include<queue>
#include<cstdio>
#include<cctype>
#include<vector>
#include<algorithm>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
const int N=1e5+1,M=1e5;
char s[N];
int m,par[N],pos[N],in[N],out[N],cnt,ans[M];
std::vector<int> e[N];
inline void add_edge(const int &u,const int &v) {
e[u].push_back(v);
par[v]=u;
}
struct Query {
int x,y,id;
bool operator < (const Query &rhs) const {
return y<rhs.y;
}
};
Query q[M];
class FenwickTree {
private:
int val[N+1];
int lowbit(const int &x) const {
return x&-x;
}
public:
void modify(int p,const int &x) {
for(;p<=cnt;p+=lowbit(p)) val[p]+=x;
}
int query(int p) const {
int ret=0;
for(;p;p-=lowbit(p)) ret+=val[p];
return ret;
}
};
FenwickTree t;
class AhoCorasick {
private:
int ch[N][26],last[N],fail[N];
int sz,new_node() {
return ++sz;
}
int idx(const char &c) const {
return c-'a';
}
public:
void insert(const char s[]) {
for(register int i=0,p=0;s[i];i++) {
if(s[i]=='P') {
pos[++pos[0]]=p;
continue;
}
if(s[i]=='B') {
p=last[p];
continue;
}
const int c=idx(s[i]);
if(!ch[p][c]) {
ch[p][c]=new_node();
last[ch[p][c]]=p;
}
p=ch[p][c];
}
}
void get_fail() {
std::queue<int> q;
for(register int i=0;i<26;i++) {
if(ch[0][i]) q.push(ch[0][i]);
}
while(!q.empty()) {
const int &x=q.front();
for(register int i=0;i<26;i++) {
int &y=ch[x][i];
if(y) q.push(y);
(y?fail[y]:y)=ch[fail[x]][i];
}
add_edge(fail[x],x);
q.pop();
}
}
void solve() const {
for(register int i=0,j=0,k=0,p=0;s[i];i++) {
if(s[i]=='P') {
if(++k==q[j].y) {
for(;j<m&&q[j].y==k;j++) {
ans[q[j].id]=t.query(out[pos[q[j].x]])-t.query(in[pos[q[j].x]]-1);
}
}
continue;
}
if(s[i]=='B') {
t.modify(in[p],-1);
p=last[p];
continue;
}
p=ch[p][idx(s[i])];
t.modify(in[p],1);
}
}
};
AhoCorasick ac;
void dfs(const int &x) {
in[x]=++cnt;
for(unsigned i=0;i<e[x].size();i++) {
const int &y=e[x][i];
dfs(y);
}
out[x]=cnt;
}
int main() {
scanf("%s",s);
ac.insert(s);
ac.get_fail();
dfs(0);
m=getint();
for(register int i=0;i<m;i++) {
q[i].x=getint();
q[i].y=getint();
q[i].id=i;
}
std::sort(&q[0],&q[m]);
ac.solve();
for(register int i=0;i<m;i++) {
printf("%d\n",ans[i]);
}
return 0;
}