做法
贪心策略
在此使用贪心。
最开始把
t
t
t 的匹配位数
j
j
j 设为
1
1
1,枚举
s
s
s 的每一位,如果当前第
i
i
i 位的字符
s
i
=
t
j
s_i = t_j
si=tj 则
j
+
1
j + 1
j+1,如果
s
i
=
?
s_i = ?
si=? 则先
s
i
=
t
j
s_i = t_j
si=tj 再
j
+
1
j + 1
j+1。直到进行到
j
=
∣
t
∣
+
1
j = |t| + 1
j=∣t∣+1 时,把
s
s
s 中剩下的
?
?
? 换成任意字符,输出
s
s
s 并结束程序。如果遍历完
s
s
s 后,
j
≠
∣
t
∣
+
1
j \not = |t| + 1
j=∣t∣+1,则无解。
贪心证明
首先,这样做符合题目要求,所以我们只需证明,如果问题有解,那么贪心策略一定能找到一组解。
对于任意一个解,我们把所有没有在第一次就匹配的位置换成第一次就匹配,就转化成了一种合法贪心解。因此有解贪心就一定能找到解。
代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 200010;
char s[N], t[N];
int main()
{
int T;
scanf("%d", &T);
while (T -- )
{
scanf("%s%s", s + 1, t + 1);
int n = strlen(s + 1), m = strlen(t + 1);
int j = 1;
for (int i = 1; i <= n; i ++ )
{
char c = s[i];
if (j <= m && (c == '?' || c == t[j]))
{
if (c == '?') s[i] = t[j];
j ++ ;
}
else if (c == '?') s[i] = 'a';
}
if (j == m + 1)
{
puts("YES");
for (int i = 1; i <= n; i ++ ) printf("%c", s[i]);
puts("");
}
else puts("NO");
}
return 0;
}