【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;
}
posted @ 2021-06-02 17:18  Jayun  阅读(81)  评论(0编辑  收藏  举报