题目链接:BZOJ – 3942
题目分析
我们发现,删掉一段 T 之后,被删除的部分前面的一段可能和后面的一段连接起来出现新的 T 。
所以我们删掉一段 T 之后应该接着被删除的位置之前的继续向后匹配。
那么我们维护一个栈,一直向后匹配,如果栈顶出现了 T ,就弹出 T 个字符,然后继续从新的栈顶向后匹配就可以了。
匹配使用 KMP 算法。
代码
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #include <cmath> using namespace std; const int MaxL = 1000000 + 5; int l, lt, Top; int Next[MaxL], f[MaxL]; char S[MaxL], T[MaxL], Str[MaxL]; void Prepare() { int j = Next[1] = 0; for (int i = 2; i <= lt; ++i) { while (j > 0 && T[j + 1] != T[i]) j = Next[j]; if (T[j + 1] == T[i]) ++j; Next[i] = j; } } int main() { scanf("%s%s", S + 1, T + 1); l = strlen(S + 1); lt = strlen(T + 1); Prepare(); int j = 0; for (int i = 1; i <= l; ++i) { Str[++Top] = S[i]; while (j > 0 && T[j + 1] != Str[Top]) j = Next[j]; if (T[j + 1] == Str[Top]) ++j; if (j == lt) { Top -= lt; j = f[Top]; } else f[Top] = j; } Str[Top + 1] = 0; printf("%s\n", Str + 1); return 0; }