CF163E e-Government 题解
前置知识
解法
一次性将所有模式串加入 AC 自动机,然后处理加入和删除,考虑单次操作对答案的贡献。
因为模式串 \(T\) 在文本串 \(S\) 中出现的次数之和等价于 \(T\) 在 \(S\) 的所有前缀中作为后缀出现的次数之和。这就很和 \(fail\) 树上跳到根节点的性质相符。
加入/删除分别对应末尾标记 \(ed\) 的 \(+1/-1\)。
单点修改加一个点到根节点这条链的区间查询可以转化为子树修改加单点查询。
转成 DFS 序后树状数组维护即可。
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define sort stable_sort
#define endl '\n'
struct node
{
int nxt,to;
}e[1000010];
int head[1000010],dfn[1000010],out[1000010],del[1000010],tot=0,cnt=0;
char s[1000010];
void add(int u,int v)
{
cnt++;
e[cnt].nxt=head[u];
e[cnt].to=v;
head[u]=cnt;
}
struct BIT
{
int c[1000010];
int lowbit(int x)
{
return x&(-x);
}
void add(int n,int x,int val)
{
for(int i=x;i<=n;i+=lowbit(i))
{
c[i]+=val;
}
}
void update(int n,int l,int r,int val)
{
add(n,l,val);
add(n,r+1,-val);
}
int getsum(int x)
{
int ans=0;
for(int i=x;i>=1;i-=lowbit(i))
{
ans+=c[i];
}
return ans;
}
}B;
struct ACM
{
int ed[1000010],fail[1000010],rt_sum;
struct trie
{
int ch[27];
}tree[1000010];
int val(char x)
{
return x-'a'+1;
}
void insert(char s[],int len,int id)
{
int x=0;
for(int i=1;i<=len;i++)
{
if(tree[x].ch[val(s[i])]==0)
{
rt_sum++;
tree[x].ch[val(s[i])]=rt_sum;
}
x=tree[x].ch[val(s[i])];
}
ed[id]=x;
}
void build()
{
queue<int>q;
for(int i=1;i<=26;i++)
{
if(tree[0].ch[i]!=0)
{
fail[tree[0].ch[i]]=0;
add(0,tree[0].ch[i]);
q.push(tree[0].ch[i]);
}
}
while(q.empty()==0)
{
int x=q.front();
q.pop();
for(int i=1;i<=26;i++)
{
if(tree[x].ch[i]==0)
{
tree[x].ch[i]=tree[fail[x]].ch[i];
}
else
{
fail[tree[x].ch[i]]=tree[fail[x]].ch[i];
add(fail[tree[x].ch[i]],tree[x].ch[i]);
q.push(tree[x].ch[i]);
}
}
}
}
int query(char s[],int len)
{
int x=0,ans=0;
for(int i=1;i<=len;i++)
{
x=tree[x].ch[val(s[i])];
ans+=B.getsum(dfn[x]);
}
cerr<<endl;
return ans;
}
}A;
void dfs(int x)
{
tot++;
dfn[x]=tot;
for(int i=head[x];i!=0;i=e[i].nxt)
{
dfs(e[i].to);
}
out[x]=tot;
}
int main()
{
int q,n,x,i;
char pd;
cin>>q>>n;
for(i=1;i<=n;i++)
{
cin>>(s+1);
A.insert(s,strlen(s+1),i);
}
A.build();
dfs(0);
for(i=1;i<=n;i++)
{
B.update(tot,dfn[A.ed[i]],out[A.ed[i]],1);
}
for(i=1;i<=q;i++)
{
cin>>pd;
if(pd=='?')
{
cin>>(s+1);
cout<<A.query(s,strlen(s+1))<<endl;
}
if(pd=='+')
{
cin>>x;
if(del[x]==1)
{
del[x]=0;
B.update(tot,dfn[A.ed[x]],out[A.ed[x]],1);
}
}
if(pd=='-')
{
cin>>x;
if(del[x]==0)
{
del[x]=1;
B.update(tot,dfn[A.ed[x]],out[A.ed[x]],-1);
}
}
}
return 0;
}
本文来自博客园,作者:hzoi_Shadow,原文链接:https://www.cnblogs.com/The-Shadow-Dragon/p/18374806,未经允许严禁转载。
版权声明:本作品采用 「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0) 进行许可。