zoukankan      html  css  js  c++  java
  • P3121 [USACO15FEB]Censoring G

    P3121 [USACO15FEB]Censoring G

    AC 自动机 多模式串匹配问题。

    首先我们对所有模式串建立一个 ACAM 。

    然后我们把文本串放上去匹配,当我们匹配到一个带标记的点的时候,说明我们目前出现了一个串,那么检查当前是否可以匹配完全,可以的话我们会直接相当于现在说明都没有匹配,也就是直接返回到根节点。

    不然的话我们就按照可撤销并查集的思路,用一个栈记录一下我们的路径然后往回跳即可。

    我们这里拿两个栈,一个记录上一个跳的编号,一个记录字符串。

    最后直接把记录字符串的那个输出即可。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    template <typename T>
    inline void read(T &x){
    	x=0;bool f=false;char ch=getchar();
    	while(!isdigit(ch)){f=(ch=='-');ch=getchar();}
    	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    	return ;
    }
    template <typename T>
    inline void write(T x){
    	if(x<0) x=-x,putchar('-');
    	if(x>9) write(x/10);
    	putchar(x%10^48);
    	return ;
    }
    const int N=1e5+5;
    int n,m;
    struct ACAM{
    	int son[26],fail,val;
    	#define son(x,i) t[x].son[i]
    	#define fail(x) t[x].fail
    	#define val(x) t[x].val
    }t[N];
    int root,cur;
    void Insert(char *str){
    	int len=strlen(str),p=root;
    	for(int i=0;i<len;i++){
    		int c=str[i]-'a';
    		if(!son(p,c)) son(p,c)=++cur;
    		p=son(p,c);
    	}
    	val(p)=len;
    	return ;
    }
    void Build(){
    	queue<int> q;
    	for(int i=0;i<26;i++) if(son(root,i)) fail(son(root,i))=root,q.push(son(root,i));
    	while(!q.empty()){
    		int x=q.front();q.pop();
    		for(int i=0;i<26;i++){
    			if(son(x,i)) fail(son(x,i))=son(fail(x),i),q.push(son(x,i));
    			else son(x,i)=son(fail(x),i);
    		}
    	}
    	return ;
    }
    int sta1[N],sta2[N],top;
    void Search(char *str){
    	int len=strlen(str),now=root;
    	for(int i=0;i<len;i++){
    		int c=str[i]-'a';
    		now=son(now,c);
    		sta1[++top]=c;
    		sta2[top]=now;
    		if(val(now)){
    			top-=val(now);
    			if(top==0) now=0;
    			else now=sta2[top];
    		}
    	}
    	return ;
    }
    char a[N],st[N];
    int main(){
    	scanf("%s",a);
    	read(n);
    	for(int i=1;i<=n;i++){
    		scanf("%s",st);
    		Insert(st);
    	}
    	Build();
    	Search(a);
    	for(int i=1;i<=top;i++) putchar('a'+sta1[i]);
    	return 0;
    }
    
  • 相关阅读:
    vue中使用第三方UI库的移动端rem适配方案
    前端规范--eslint standard
    从上往下打印二叉树
    栈的压入,弹出序列
    随机森林
    LR
    顺时针打印矩阵
    包含min函数的栈
    树的子结构
    合并两个有序链表
  • 原文地址:https://www.cnblogs.com/Akmaey/p/14678201.html
Copyright © 2011-2022 走看看