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;
}