L2-2 小 Z 的神奇贴纸
题目背景
小 Z 偶然发现了一包神奇的贴纸,这些贴纸上的字符串都是相同的,聪明的他想到了一个问题:只使用这些神奇的贴纸,能否拼贴出他想要的字符串?
题目描述
形式化来说,给定两个由小写英文字母组成的字符串 S S S 和 T T T,其长度分别为 n n n 和 m m m,保证 n ≥ m n\geq m n≥m,你可以进行无限次操作 P \mathcal P P,将字符串 S [ i , i + m − 1 ] S_{[i, i + m - 1]} S[i,i+m−1]( 1 ≤ i ≤ n − m + 1 1\leq i\leq n - m + 1 1≤i≤n−m+1)替换为字符串 T T T。
现有字符串 X X X,长度为 n n n,初始为空,问 X X X 是否可以经过有限次操作 P \mathcal P P 后变为字符串 S S S?
例如,若字符串
S
S
S 为 llalastst
,字符串
T
T
T 为 last
,那么
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????→Pllastlast→Pllalastst
再如,若字符串
S
S
S 为 xyx
,字符串
T
T
T 为 yx
,那么可以证明:
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
1≤n≤1000 且
m
=
1
m = 1
m=1。
对于另外
50
%
50\%
50% 的数据,保证
1
≤
n
≤
1000
1\leq n\leq 1000
1≤n≤1000。
对于
100
%
100\%
100% 的数据,保证
1
≤
t
≤
10
1\leq t\leq 10
1≤t≤10,
1
≤
n
≤
1
0
5
1\leq n\leq 10^5
1≤n≤105,
1
≤
m
≤
5
1\leq m\leq 5
1≤m≤5。
保证给出的字符串均由小写英文字母构成,且满足
n
≥
m
n\geq m
n≥m。
思路提示
首先将问题由 “从空串通过修改操作变为 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
n−m+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]
[L−m+1,L],...,[R,R+m−1]。
当删除区间
[
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;
}