题目链接:https://www.luogu.com.cn/problem/P3121
洛谷P3121 [USACO15FEB]Censoring G
AC自动机
题目大意为给出一个主字符串以及若干个子字符串,要求输出从主串中删除所有子串之后的结果字符串。
入门AC自动机的题,将每个子字符串压入trie中,再从头遍历一遍主串,遇到匹配的部分就删除,最后输出即可。
#include<bits/stdc++.h>
#define next next_
#define y1 yy
using namespace std;
using ll=long long;
using ull=unsigned long long;
using pii=pair<int,int>;
using pll=pair<ll,ll>;
int _;
int n,tot=1,pos[200010];
char ans[200010];
string s,ss;
struct trie{
int tran[26];
int len;
int fail;
int cnt;
}t[200010];
void insert(string s){
int len=s.size();
int u=1;
for(int i=0;i<len;i++){
if(!t[u].tran[s[i]-'a']) t[u].tran[s[i]-'a']=++tot;
u=t[u].tran[s[i]-'a'];
}
t[u].cnt++;
t[u].len=len;
}
void buildfail(){
for(int i=0;i<26;i++) t[0].tran[i]=1;
queue<int> q;
q.push(1);
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=0;i<26;i++){
int v=t[u].fail,w;
while(!t[v].tran[i]) v=t[v].fail;
v=t[v].tran[i];
w=t[u].tran[i];
if(w) t[w].fail=v,q.push(w);
else t[u].tran[i]=v;
}
}
}
void work(){
cin>>s;
scanf("%d",&n);
for(int i=1;i<=n;i++){
cin>>ss;
insert(ss);
}
buildfail();
int len=s.size(),now=1,p=0;
pos[0]=1;
for(int i=0;i<len;i++){
ans[++p]=s[i];
now=t[now].tran[s[i]-'a'];
pos[p]=now;
if(t[now].cnt){
p-=t[now].len;
now=pos[p];
}
}
for(int i=1;i<=p;i++) printf("%c",ans[i]);
}
int main(){
// scanf("%d",&_);
_=1;
while(_--){
work();
}
return 0;
}