【Luogu P4824】[USACO15FEB]Censoring S
链接:
题目大意:
在 \(S\) 中从头开始寻找屏蔽词,一旦找到一个屏蔽词,就删除它,然后又从头开始寻找(而不是接着往下找)。
只有一个屏蔽词。
正文:
单模式串匹配,考虑用 KMP。如果匹配不到,则入栈;否则记录一下当前位置,并将当前匹配到的位置 \(i\) 往前移,并出栈。
但是这么做有一个弊端:这不是链表,如果贸然把 \(i\) 往前移会死循环。所以考虑用链表维护,在往前移时,指针往后指。
代码:
const int N = 1e6 + 10;
inline ll Read()
{
ll x = 0, f = 1;
char c = getchar();
while (c != '-' && (c < '0' || c > '9')) c = getchar();
if (c == '-') f = -f, c = getchar();
while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
return x * f;
}
int n;
char s[N], t[N], ans[N];
int nxt[N], to[N], a[N];
int top, m;
struct Stack
{
int i, j;
}stk[N];
void KMP(char *s, char *t, int op = 1)
{
int j = 0, Slen = strlen(s), Tlen = strlen(t);
for (int i = op; i < Tlen; i = to[i])
{
while (j && t[i] != s[j]) j = nxt[j];
if (t[i] == s[j]) j++;
if (op) nxt[i + 1] = j;
else
{
if (j == Slen)
a[i] = Slen, top -= Slen - 1, to[stk[top].i] = i + 1, i = stk[top].i, j = stk[top].j;
else stk[++top] = (Stack){i, j};
}
}
if (!op)
{
for (int i = Tlen - 1, Dlt = 0; ~i; i--)
{
Dlt += a[i];
if (Dlt) Dlt--;
else ans[m++] = t[i];
}
for (int i = m - 1; ~i; i--) printf("%c", ans[i]);
}
}
int main()
{
scanf("%s%s", t, s); n = strlen(t);
for (int i = 0; i < n; i++) to[i] = i + 1;
KMP(s, s);
KMP(s, t, 0);
return 0;
}