拿栈维护原串
如果AC自动机上跑到一个位置能匹配某个子串,就让
top
t
o
p
减去这个子串的长度
接着该从哪里匹配呢?
再开一个栈维护即可
Trie图的 nex n e x 不路径压缩会T的很惨….
代码如下:
#include<cstring>
#include<ctype.h>
#include<cstdio>
#include<queue>
#define N 10000050
using namespace std;
inline int read(){
int x=0,f=1;char c;
do c=getchar(),f=c=='-'?-1:f; while(!isdigit(c));
do x=(x<<3)+(x<<1)+c-'0',c=getchar(); while(isdigit(c));
return x*f;
}
int n,top;
char c[N],s[N];
struct Node{
Node *ch[26],*nex;
int len;
Node():nex(NULL),len(0){
for(int i=0;i<26;i++)
ch[i]=NULL;
}
}*root=new Node;
Node *st[N];
queue<Node*>q;
struct Aho_Corasick_Automaton{
inline void Insert(char *s){
int len=strlen(s+1);
Node *x=root;
for(int i=1;i<=len;i++){
if(!x->ch[s[i]-'a']) x->ch[s[i]-'a']=new Node;
x=x->ch[s[i]-'a'];
}
x->len=len;
}
inline void GetFail(){
for(int i=0;i<26;i++)
if(root->ch[i]) q.push(root->ch[i]),root->ch[i]->nex=root;
else root->ch[i]=root;
while(!q.empty()){
Node *x=q.front();q.pop();
for(int i=0;i<26;i++)
if(x->ch[i]) x->ch[i]->nex=x->nex->ch[i],q.push(x->ch[i]);
else x->ch[i]=x->nex->ch[i];
Node *tmp=x->nex;
while(tmp!=root && !tmp->len) tmp=tmp->nex;
if(!x->len) x->len=tmp->len;
x->nex=tmp;///不写这个路径压缩会特别慢...
}
}
inline void Match(){
Node *x=root;
st[0]=root;
int len=strlen(c+1);
for(int i=1;i<=len;i++){
x=x->ch[c[i]-'a'];
s[++top]=c[i];
st[top]=x;
if(x->len){
top-=x->len;
x=st[top];
}
}
}
}AC;
int main(){
scanf("%s",c+1);
n=read();
for(int i=1;i<=n;i++){
scanf("%s",s+1);
AC.Insert(s);
}
AC.GetFail();
AC.Match();
for(int i=1;i<=top;i++)
printf("%c",s[i]);
return 0;
}