2021-2022 ICPC, NERC, Northern Eurasia Onsite (Unrated, Online Mirror, ICPC Rules, Teams Preferred) D. Deletive Editing

发布时间 2023-09-13 20:12:21作者: zsxuan

给一个大写字符串 \(S_{txt}\) ,每次操作可以删除一个字符 \(C\) ,且只能删除 \(S_{txt}\) 中的第一个字符 \(C\) 。给一个字符串 \(S_{pat}\) ,询问 \(S_{pat}\) 能否由 \(S_{txt}\) 经过若干次字符删除后得到。

逆向:“删除第一个字符 \(C\) ”的逆向为,“在第一个字符 \(C\) 左边任意位置增加一个字符 \(C\) ”。即 \(S_{txt}\) 可视为 \(S_{pat}\) 增加字符得到。

  • 于是,对于 \(S_{pat}\) 中的任意字符 \(C\) ,若 \(C\)\(S_{pat}\) 右起第 \(x\)\(C\) ,则也会是 \(S_{txt}\) 右起第 \(x\)\(C\)

故只需要使用一个指针 \(i\) 从右到左扫 \(S_{pat}\) ,同时使用指针 \(l\) 从右往左找 \(S_{pat_{i}}\) 的匹配字符。判断 \(S_{pat}\)\(S_{txt}\) 的子序列,且满足上述限制即可从 \(S_{txt}\) 删除字符得到 \(S_{pat}\)

只需判断 \(S_{txt}\)\(S_{txt}.length\) 个字符满足限制。

view
#include <bits/stdc++.h>
void solve() {
	std::string s_txt, s_pat; std::cin >> s_txt >> s_pat;
	int n = s_txt.length(), m = s_pat.length();
	int l = n - 1, ok = 0;
	int cnt_txt[26] = {0};
	int cnt_pat[26] = {0};
	for (int i = m - 1; ~i; --i, --l) {
		cnt_pat[s_pat[i] - 'A']++;
		while (l >= 0 && s_txt[l] != s_pat[i]) {
			cnt_txt[s_txt[l] - 'A']++;
			l--;
		}
		if (l < 0) break;
		cnt_txt[s_txt[l] - 'A']++;
		ok += (cnt_pat[s_pat[i] - 'A'] == cnt_txt[s_txt[l] - 'A']);
	}
	std::cout << (ok == m ? "YES" : "NO") << '\n';
}
signed main() {
	int _ = 1; std::cin >> _;
	while (_--) solve();
	return 0;
}