显然是个AC自动机
考虑删除完单词后怎么回到前面
可以开一个栈
存到每个字符时匹配的位置
然后就可以搞了
答案也用一个栈存
每次删单词时把答案栈里的单词也弹出来
最后输出栈里的单词就好了
数据有毒,输出后要换行,不然会WA...
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<queue> using namespace std; const int N=2e5+7; const int M=2e6+7; int n,l[N];//l存每个单词长度,方便弹出栈 char s[N],a[N]; int c[M][27],pd[M],fail[M],cnt,g[M];//AC自动机 inline void ins(int k)//插入第k个单词 { int u=0; for(int i=0;i<l[k];i++) { int v=a[i]-'a'+1; if(!c[u][v]) c[u][v]=++cnt; u=c[u][v]; } pd[u]=k; } queue <int> q; inline void pre()//预处理 { for(int i=1;i<=26;i++) if(c[0][i]) q.push(c[0][i]); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=1;i<=26;i++) { int v=c[u][i]; if(!v) c[u][i]=c[fail[u]][i]; else { fail[v]=c[fail[u]][i]; g[v]=pd[fail[v]] ? fail[v] : g[fail[v]]; q.push(v); } } } } char q2[N];//答案栈 int q1[N],t1,t2; inline void query() { int u=0,len=strlen(s); for(int i=0;i<len;i++) { int v=s[i]-'a'+1; u=c[u][v]; q1[++t1]=u; q2[++t2]=s[i];//入栈 for(int j=u;j;j=g[j]) if(pd[j])//如果有单词就弹出 { t1-=l[pd[j]]; t2-=l[pd[j]]; u=q1[t1]; break;//题目保证任何单词都不是其他单词的子串 } } for(int i=1;i<=t2;i++) printf("%c",q2[i]); printf(" ");//坑点 } int main() { scanf("%s",s); cin>>n; for(int i=1;i<=n;i++) { scanf("%s",a); l[i]=strlen(a); ins(i); } pre(); query(); return 0; }