小 Z 的神奇贴纸

文章讨论了如何使用一包特殊贴纸进行替换操作,判断是否能通过无限次操作将一个初始为空的字符串X转换成给定的目标字符串S。通过DFS策略,解决字符串S是否可以通过P操作变为空的问题。
摘要由CSDN通过智能技术生成

L2-2 小 Z 的神奇贴纸

题目背景

小 Z 偶然发现了一包神奇的贴纸,这些贴纸上的字符串都是相同的,聪明的他想到了一个问题:只使用这些神奇的贴纸,能否拼贴出他想要的字符串?

题目描述

形式化来说,给定两个由小写英文字母组成的字符串 S S S T T T,其长度分别为 n n n m m m,保证 n ≥ m n\geq m nm,你可以进行无限次操作 P \mathcal P P,将字符串 S [ i , i + m − 1 ] S_{[i, i + m - 1]} S[i,i+m1] 1 ≤ i ≤ n − m + 1 1\leq i\leq n - m + 1 1inm+1)替换为字符串 T T T

现有字符串 X X X,长度为 n n n,初始为空,问 X X X 是否可以经过有限次操作 P \mathcal P P 后变为字符串 S S S

例如,若字符串 S S Sllalastst,字符串 T T Tlast,那么 X X X 就可以经过 4 4 4 次操作 P \mathcal P P 变为字符串 S S S,以下为具体步骤:

? ? ? ? ? ? ? ? ? → P l a s t ‾ ? ? ? ? ? → P l l a s t ‾ ? ? ? ? → P l l a s t l a s t ‾ → P l l a l a s t ‾ s t \mathrm{?????????}\overset{\mathcal{P} }{\rightarrow} \mathrm{\underline{last}?????}\overset{\mathcal{P} }{\rightarrow} \mathrm{l\underline{last}????}\overset{\mathcal{P} }{\rightarrow} \mathrm{llast\underline{last}}\overset{\mathcal{P} }{\rightarrow} \mathrm{lla\underline{last}st} ?????????Plast?????Pllast????PllastlastPllalastst

再如,若字符串 S S Sxyx,字符串 T T Tyx,那么可以证明: X X X 不可能经过有限次操作 P \mathcal P P 变为字符串 S S S

输入格式

本题包含多组测试数据。
第一行一个正整数 t t t,代表测试数据的组数。
之后每两行为一组测试数据,每组中的第一行代表字符串 S S S,每组中的第二行代表字符串 T T T

输出格式

输出共 t t t 行,分别代表每组的答案。
对于每组测试数据,若 X X X 可以在给定的 T T T 下经过有限次操作 P \mathcal P P 变为字符串 S S S,则输出 Yes;否则,输出 No

样例 #1

样例输入 #1

2
llalastst
last
xyx
yx

样例输出 #1

Yes
No

提示说明

样例解释:

见上方题目描述。

数据规模与约定

对于 10 % 10\% 10% 的数据,保证 1 ≤ n ≤ 1000 1\leq n\leq 1000 1n1000 m = 1 m = 1 m=1
对于另外 50 % 50\% 50% 的数据,保证 1 ≤ n ≤ 1000 1\leq n\leq 1000 1n1000
对于 100 % 100\% 100% 的数据,保证 1 ≤ t ≤ 10 1\leq t\leq 10 1t10 1 ≤ n ≤ 1 0 5 1\leq n\leq 10^5 1n105 1 ≤ m ≤ 5 1\leq m\leq 5 1m5
保证给出的字符串均由小写英文字母构成,且满足 n ≥ m n\geq m nm

思路提示

首先将问题由 “从空串通过修改操作变为 S S S” 转化为 “从 S S S 通过删除操作变为空串” 。

对于 10 % 10\% 10% 的数据,只需要判断字符串 S S S中的字母是否和 T T T中唯一的字母一致即可。
对于 60 % 60\% 60% 的数据,注意到每个长为 m m m 的区间最多只会删除一次,我们只需枚举 n − m + 1 n-m+1 nm+1次,每次找到一个可以删除,且未被删除的区间删除即可,时间复杂度 O ( m n 2 ) O(mn^2) O(mn2)
对于 100 % 100\% 100% 的数据,找到 “贴在最上面的那张贴纸”,设它贴在区间 [ L , R ] [L,R] [L,R]上,则受它影响的区间有 [ L − m + 1 , L ] , . . . , [ R , R + m − 1 ] [L-m+1,L],...,[R,R+m-1] [Lm+1,L],...,[R,R+m1]

当删除区间 [ L , R ] [L,R] [L,R] 时,原本这些不合法的区间可能又变成合法状态,只需要再次判断这些区间是否可以删除即可。
可以使用深度优先搜索算法(DFS)模拟这一过程,时间复杂度 O ( m n 2 ) O(mn^2) O(mn2)

代码内容

#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int n, m;
char s[N], t[N];
void dfs(int p) 
{
	if(p < 1 || p + m - 1 > n) return;
	int cnt = 0;
	bool flg = true;
	for(int i = 1; i <= m; i++) {
		if(s[p + i - 1] == '*') ++cnt;
		if(s[p + i - 1] != '*' && s[p + i - 1] != t[i]) flg = false;
	}
	if(cnt == m || !flg) return;
	for(int i = 1; i <= m; i++)
		s[p + i - 1] = '*';
	for(int i = 1; i <= m; i++)
		dfs(p - i), dfs(p + i);
}

void solve() 
{
	scanf("%s%s", s + 1, t + 1);
	n = strlen(s + 1); m = strlen(t + 1);
	for(int i = 1; i <= n; i++) {
		bool flg = true;
		for(int j = 1; j <= m; j++)
			if(s[i + j - 1] != '*' && s[i + j - 1] != t[j]) flg = false;
		if(flg) dfs(i);
	}
	for(int i = 1; i <= n; i++)
		if(s[i] != '*') return puts("No"), void();
	puts("Yes");
}

int main() 
{
	int t; scanf("%d", &t);
	while(t--) solve();
	return 0;
}

  • 10
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Pretty Boy Fox

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值