把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

CF163E e-Government

题面传送门
像这种多字符串匹配就可以考虑建出AC自动机来搞。
如果没有增删操作直接匹配即可。
但是这道题有增删操作。每个节点fail子树内的权值会变。
所以可以把fail树的dfs序跑出来在上面维护树状数组即可。
讲道理这道题询问很多修改很少应该套分块才是,但是出题人没卡就不管了
时间复杂度\(O(\sum|S|logn)\)
代码实现:

#include<cstdio>
#include<queue>
#include<cstring>
#define beg(x) int cur=s.h[x]
#define end cur
#define go cur=tmp.z
using namespace std;
int n,m,k,x,y,z,flag[100039],bg[1000039],id[1000039],cnt,now,siz[1000039],g[1000039],dfn,tot;
char a[1000039],_s;
struct AC{int son[26],fail;}f[1000039];
inline void get(int x){
	register int i;now=0;
	for(i=1;i<=k;i++)
	now=f[now].son[a[i]-'a']?f[now].son[a[i]-'a']:(f[now].son[a[i]-'a']=++cnt);id[x]=now;
}
queue<int> q;
inline void bfs(){
	register int i; 
	for(i=0;i<=25;i++)if(f[0].son[i]) q.push(f[0].son[i]);
	while(!q.empty()){
		now=q.front();q.pop();
		for(i=0;i<=25;i++){
			if(f[now].son[i]) f[f[now].son[i]].fail=f[f[now].fail].son[i],q.push(f[now].son[i]);
			else f[now].son[i]=f[f[now].fail].son[i];
		}
	}
}
struct yyy{int to,z;};
struct ljb{
	int head,h[1000039];yyy f[1000039];
	inline void add(int x,int y){f[++head]=(yyy){y,h[x]};h[x]=head;}
}s;
inline void dfs(int x){
	bg[x]=++dfn;yyy tmp;siz[x]=1;
	for(beg(x);end;go)tmp=s.f[cur],dfs(tmp.to),siz[x]+=siz[tmp.to];
}
inline void get(int x,int y){while(x<=dfn) g[x]+=y,x+=x&-x;}
inline int find(int x){int ans=0;while(x) ans+=g[x],x-=x&-x;return ans;}
int main(){
	freopen("1.in","r",stdin);
	register int i,j;
	scanf("%d%d",&m,&n);
	for(i=1;i<=n;i++)scanf("%s",a+1),k=strlen(a+1),get(i);bfs();
	for(i=1;i<=cnt;i++) s.add(f[i].fail,i);
	dfs(0);
	for(i=1;i<=n;i++) get(bg[id[i]],1),get(bg[id[i]]+siz[id[i]],-1),flag[i]=1;
	for(i=1;i<=m;i++){
		_s=getchar();
		while(_s!='?'&&_s!='+'&&_s!='-') _s=getchar();
		if(_s=='+'){
			scanf("%d",&x);
			if(!flag[x]) get(bg[id[x]],1),get(bg[id[x]]+siz[id[x]],-1),flag[x]=1;
		}
		else if(_s=='-'){
			scanf("%d",&x);
			if(flag[x])flag[x]=0,get(bg[id[x]],-1),get(bg[id[x]]+siz[id[x]],1);
		}
		else{
			scanf("%s",a+1);k=strlen(a+1);now=0;tot=0;
			for(j=1;j<=k;j++)now=f[now].son[a[j]-'a'],tot+=find(bg[now]);
 		    printf("%d\n",tot);
		}
	}
}
posted @ 2021-02-05 18:31  275307894a  阅读(48)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end