Luogu P4824 [USACO15FEB] Censoring S

发布时间 2023-06-11 17:39:57作者: 觉清风

[USACO15FEB] Censoring S

题面翻译

Farmer John为他的奶牛们订阅了Good Hooveskeeping杂志,因此他们在谷仓等待挤奶期间,可以有足够的文章可供阅读。不幸的是,最新一期的文章包含一篇关于如何烹制完美牛排的不恰当的文章,FJ不愿让他的奶牛们看到这些内容。

FJ已经根据杂志的所有文字,创建了一个字符串 $ S $ ( $ S $ 的长度保证不超过 $ 10^6 $ ),他想删除其中的子串 $ T $ ,他将删去 $ S $ 中第一次出现的子串 $ T $ ,然后不断重复这一过程,直到 $ S $ 中不存在子串 $ T $ 。

注意:每次删除一个子串后,可能会出现一个新的子串 $ T $ (说白了就是删除之后,两端的字符串有可能会拼接出来一个新的子串 $ T $ )。

输入格式:第一行是字符串 $ S $ ,第二行输入字符串 $ T $ ,保证 $ S $ 的长度大于等于 $ T $ 的长度, $ S $ 和 $ T $ 都只由小写字母组成。

输出格式:输出经过处理后的字符串,保证处理后的字符串不会为空串。

Translated by @StudyingFather

题目描述

Farmer John has purchased a subscription to Good Hooveskeeping magazine for his cows, so they have plenty of material to read while waiting around in the barn during milking sessions. Unfortunately, the latest issue contains a rather inappropriate article on how to cook the perfect steak, which FJ would rather his cows not see (clearly, the magazine is in need of better editorial oversight).

FJ has taken all of the text from the magazine to create the string \(S\) of length at most 10^6 characters. From this, he would like to remove occurrences of a substring \(T\) to censor the inappropriate content. To do this, Farmer John finds the first occurrence of \(T\) in \(S\) and deletes it. He then repeats the process again, deleting the first occurrence of \(T\) again, continuing until there are no more occurrences of \(T\) in \(S\). Note that the deletion of one occurrence might create a new occurrence of \(T\) that didn't exist before.

Please help FJ determine the final contents of \(S\) after censoring is complete.

输入格式

The first line will contain \(S\). The second line will contain \(T\). The length of \(T\) will be at most that of \(S\), and all characters of \(S\) and \(T\) will be lower-case alphabet characters (in the range a..z).

输出格式

The string \(S\) after all deletions are complete. It is guaranteed that \(S\) will not become empty during the deletion process.

样例 #1

样例输入 #1

whatthemomooofun
moo

样例输出 #1

whatthefun
//注意题目里要求像消消乐一样
//如果接触的字符串匹配(消掉之后的两边接触的字符串也算)就直接消掉
//而不是先消一轮之后 再消之前消掉的两边的字符串 
//以下是错误代码
/*
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<queue>

using namespace std;

char a[5211314 >> 2], b[5211314 >> 2], tem[5211314 >> 2];
int nex[5211314 >> 2], l1, l2;
int l[5211314 >> 2], r[5211314 >> 2], count_;

int main() {
	scanf("%s", a + 1);
	scanf("%s", b + 1);
	l1 = strlen(a + 1);
	l2 = strlen(b + 1);
	nex[0] = 1;
	for (int i = 2, j = 0; i <= l2; ++ i) {
		while (j > 0 && b[j + 1] != b[i]) {
			j = nex[j];
		}
		if (b[j + 1] == b[i]) j ++;
		nex[i] = j;
	}
	do {
		count_ = 0;
		for (int i = 1, j = 0; i <= l1; ++ i) {
			while (j > 0 && b[j + 1] != a[i]) {
				j = nex[j];
			}
			if (b[j + 1] == a[i]) j ++;
			if (j == l2) {
				count_ ++;
				l[count_] = i - l2 + 1;
				r[count_] = i;
				j = 0;
			}
		}
		int len = 0;
		for (int i = 1, temp = 1; i <= l1; ++ i) {
			if (i == l[temp]) {
				i = r[temp];
				temp ++;
			}
			else {
				len ++;
				tem[len] = a[i];
			}
		}
		memset(l, 0, sizeof(l));
		memset(r, 0, sizeof(r));
		l1 = len;
		for (int i = 1; i <= l1; ++ i) {
			a[i] = tem[i];
		}
	} while(count_ != 0);
	for (int i = 1; i <= l1; ++ i) {
		cout << a[i];
	}
	cout << endl;
	return 0;
}
*/ 
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>

using namespace std;

char a[5211314 >> 2], b[5211314 >> 2];
int nex[5211314 >> 2], l1, l2;
int sta[5211314 >> 2], top, record[5211314 >> 2];

int main() {
	scanf("%s", a + 1);
	scanf("%s", b + 1);
	l1 = strlen(a + 1);
	l2 = strlen(b + 1);
	nex[0] = 1;
	for (int i = 2, j = 0; i <= l2; ++ i) {
		while (j > 0 && b[j + 1] != b[i]) {
			j = nex[j];
		}
		if (b[j + 1] == b[i]) j ++;
		nex[i] = j;
	}
	for (int i = 1, j = 0; i <= l1; ++ i) {
		while (j > 0 && b[j + 1] != a[i]) {
			j = nex[j];
		}
		if (b[j + 1] == a[i]) j ++;
		record[i] = j;
		//记录第i个字符对应的j 
		sta[++ top] = i;
		//将i压入栈内 
		if (j == l2) {
			//若可以匹配 
			top -= l2;
			//将栈的大小减去匹配字符串的长度 
			j = record[sta[top]];
			//将先前记录的字符对应的j值赋上 
		}
	}
	for (int i = 1; i <= top; ++ i) {
		cout << a[sta[i]];
		//输出 
	}
	return 0;
}