题意:在文本串上删除一些字符串 每次优先删除从左边开始第一个满足的
删除后剩下的串连在一起重复删除步骤 直到不能删
题解:建fail 用栈存当前放进了那些字符 如果可以删 fail指针跳到前面去
好菜啊TAT 原来还有个优化
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; char t[100005]; char s[100005]; int n, cnt, tot; int ch[100005][26]; int val[100005]; int que[100005]; int fail[100005]; char ans[100005]; int id[100005]; void insert() { int len = strlen(s); int now = 1; for(int i = 0; i < len; i++) { int c = s[i] - 'a'; if(!ch[now][c]) ch[now][c] = ++cnt; now = ch[now][c]; } val[now] = len; } void getfail() { int l1 = 1, r1 = 0; que[++r1] = 1; while(l1 <= r1) { int now = que[l1]; l1++; for(int i = 0; i < 26; i++) { if(ch[now][i]) { int y = fail[now]; while(!ch[y][i]) y = fail[y]; fail[ch[now][i]] = ch[y][i]; que[++r1] = ch[now][i]; } else ch[now][i] = ch[fail[now]][i]; } } } void init() { cnt = 1; tot = 0; id[0] = 1; for(int i = 0; i < 26; i++) ch[0][i] = 1; } int main() { init(); scanf("%s", t + 1); int len = strlen(t + 1); scanf("%d", &n); for(int i = 1; i <= n; i++) { scanf("%s", s); insert(); } getfail(); int now = 1; for(int i = 1; i <= len; i++) { int c = t[i] - 'a'; now = ch[now][c]; id[++tot] = now; ans[tot] = t[i]; if(val[now]) { tot -= val[now]; now = id[tot]; } } for(int i = 1; i <= tot; i++) printf("%c", ans[i]); puts(""); return 0; }