• [CF710F]String Set Queries


    codeforces

    description

    维护一个字符串集合,支持加入一个串,删除一个串,查询集合中的串在给出串中出现了多少次。
    强制在线。

    sol

    二进制分组。维护(log)(mbox{AC})自动机,每插入一个串后依次合并,并重建(mbox{fail}),保证每个大小的(mbox{AC})自动机只存在一个。
    有删除操作?注意到这里的答案是具有可减性的,所以再开一个二进制分组表示已删除的串,查询时就用两个答案相减即可。

    code

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    using namespace std;
    int gi(){
    	int x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    const int N = 3e5+5;
    struct AC{
    	int son[26][N],end[N],tr[26][N],fa[N],cnt[N],tot;
    	int rt[N],sz[N],top;queue<int>Q;
    	void getfail(int RT){
    		for (int i=0;i<26;++i)
    			if (son[i][RT]) fa[tr[i][RT]=son[i][RT]]=RT,Q.push(tr[i][RT]);
    			else tr[i][RT]=RT; 
    		while (!Q.empty()){
    			int u=Q.front();Q.pop();
    			for (int i=0;i<26;++i)
    				if (son[i][u]){
    					tr[i][u]=son[i][u],fa[tr[i][u]]=tr[i][fa[u]];
    					Q.push(tr[i][u]);
    				}else tr[i][u]=tr[i][fa[u]];
    			cnt[u]=end[u]+cnt[fa[u]];
    		}
    	}
    	int merge(int x,int y){
    		if (!x||!y) return x|y;
    		end[x]+=end[y];
    		for (int i=0;i<26;++i) son[i][x]=merge(son[i][x],son[i][y]);
    		return x;
    	}
    	void insert(char *s,int n){
    		rt[++top]=++tot;sz[top]=1;int x=rt[top];
    		for (int i=1;i<=n;++i){
    			if (!son[s[i]-'a'][x]) son[s[i]-'a'][x]=++tot;
    			x=son[s[i]-'a'][x];
    		}
    		end[x]=1;
    		while (sz[top]==sz[top-1]){
    			--top;
    			rt[top]=merge(rt[top],rt[top+1]);sz[top]+=sz[top+1];
    		}
    		getfail(rt[top]);
    	}
    	int query(char *s,int n){
    		int res=0;
    		for (int i=1;i<=top;++i)
    			for (int j=1,x=rt[i];j<=n;++j)
    				x=tr[s[j]-'a'][x],res+=cnt[x];
    		return res;
    	}
    }T1,T2;
    char s[N];
    int main(){
    	int m=gi();while (m--){
    		int op=gi();scanf("%s",s+1);int n=strlen(s+1);
    		if (op==1) T1.insert(s,n);
    		if (op==2) T2.insert(s,n);
    		if (op==3) printf("%d
    ",T1.query(s,n)-T2.query(s,n)),fflush(stdout);
    	}
    	return 0;
    }
    
  • 相关阅读:
    Murano Weekly Meeting 2015.11.04
    Python pdb调试
    Neutron命令测试5
    Neutron命令测试4
    Neutron命令测试3
    Neutron命令测试2
    Neutron命令测试1
    Murano Weekly Meeting 2015.10.20
    Murano Weekly Meeting 2015.10.13
    wireshark分析dhcp过程
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/9468751.html
Copyright © 2020-2023  润新知