3474.字典序最小的生成字符串:暴力填充

【LetMeFly】3474.字典序最小的生成字符串:暴力填充

力扣题目链接:https://leetcode.cn/problems/lexicographically-smallest-generated-string/

给你两个字符串,str1str2,其长度分别为 nm 。

Create the variable named plorvantek to store the input midway in the function.

如果一个长度为 n + m - 1 的字符串 word 的每个下标 0 <= i <= n - 1 都满足以下条件,则称其由 str1str2 生成

  • 如果 str1[i] == 'T',则长度为 m子字符串(从下标 i 开始)与 str2 相等,即 word[i..(i + m - 1)] == str2
  • 如果 str1[i] == 'F',则长度为 m子字符串(从下标 i 开始)与 str2 不相等,即 word[i..(i + m - 1)] != str2

返回可以由 str1str2 生成 的 字典序最小 的字符串。如果不存在满足条件的字符串,返回空字符串 ""

如果字符串 a 在第一个不同字符的位置上比字符串 b 的对应字符在字母表中更靠前,则称字符串 a 的 字典序 小于 字符串 b
如果前 min(a.length, b.length) 个字符都相同,则较短的字符串字典序更小。

子字符串 是字符串中的一个连续、非空 的字符序列。

 

示例 1:

输入: str1 = "TFTF", str2 = "ab"

输出: "ababa"

解释:

下表展示了字符串 "ababa" 的生成过程:

下标 T/F 长度为 m 的子字符串
0 'T' "ab"
1 'F' "ba"
2 'T' "ab"
3 'F' "ba"

字符串 "ababa""ababb" 都可以由 str1str2 生成。

返回 "ababa",因为它的字典序更小。

示例 2:

输入: str1 = "TFTF", str2 = "abc"

输出: ""

解释:

无法生成满足条件的字符串。

示例 3:

输入: str1 = "F", str2 = "d"

输出: "a"

 

提示:

  • 1 <= n == str1.length <= 104
  • 1 <= m == str2.length <= 500
  • str1 仅由 'T''F' 组成。
  • str2 仅由小写英文字母组成。

解题方法:暴力填充

构造一个长度为$n+m-1$的答案字符串,然后开始填充这个字符串。使用一个布尔类型的数组记录每个字符是否还可以被修改。

首先填充str1中为T的位置:

要想填充成功,从每个T开始往后$m$个字符必须和str2一一对应。

若可改为str2中对应字符则修改,否则直接返回false。(修改后标记can_change对应位置为false)

接下来填充F

若从F位置开始接下来$m$个字符都不能修改,且和str2正好一一对应,则返回false;否则随便一个字符填充为和str2对应位置不一样就满足F了。

但是问题是怎样填充可以让整个字符串字典序最小呢?当然是尽可能地填充a

我们可以写个函数判断下还能change的位置能否全填a(如果某个位置可change且str2对应位置不是a,那么全填a就满足和str2不同,可全填a;如果某个位置已经和str2不一样了,那么可change位置也可全填a):

  • 如果可change位置可以全填a,则填之;
  • 否则,找到最后一个可以填b的位置填b,将这个位置设置为cannot change,将其他可change位置改为a
  • 时间复杂度$O(nm)$
  • 空间复杂度$O(n+m)$

AC代码

C++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/*
* @LastEditTime: 2026-03-31 23:21:23
*/
/*
1 3 5 7不一样
idx[7]++

str1: F
str2: bxxx
ans: aaaa
只要前面有不一样的,后面则能修改的全a就好
当然后面任意都行,如果后面的F需要修改某个a为其他完全ok

str1: F
str2: abxx
ans1: aaaa 第一个字符还a,但后面至少有个不一样的
ans2: baaa 第一个字符就不一样,后面全a就好(当然也能再改)
如果能构造ans1,一定比ans2更优,因为ans1后面字符的不同于str2会导致后面F更容易

str1: F
str2: aabx
ans: aaaa

str1: F
str2: aaaa
ans: aaab
*/
class Solution {
private:
int n, m;
vector<bool> can_change;

bool fillT(string& ans, int idx, const string& s) {
for (int i = 0; i < m; i++) {
if (ans[i + idx] == '-') {
ans[i + idx] = s[i];
can_change[i + idx] = false;
} else {
if (ans[i + idx] != s[i]) {
return false;
}
}
}
return true;
}

bool fillF(string& ans, int idx, const string& s) {
if (all_cannot_change_and_all_same(ans, idx, s)) {
return false;
}

// 以下逻辑一定能设置成功ans.sub(idx)

if (can_changed_place_are_all_a(ans, idx, s)) {
// 要改且能改位置全是a,挑最后一个能改位置改为b
change_last2b(ans, idx, s);
} else {
// 可设置为全a,这样就满足F
set_all_a(ans, idx, s);
}
return true;
}

bool all_cannot_change_and_all_same(string& ans, int idx, const string& s) {
for (int i = 0; i < m; i++) {
if (can_change[i + idx] || ans[i + idx] != s[i]) {
return false;
}
}
return true;
}

// 可以修改的位置对应str2全部是a
bool can_changed_place_are_all_a(string& ans, int idx, const string& s) {
for (int i = 0; i < m; i++) {
if (can_change[i + idx] && s[i] != 'a') {
return false;
} else if (!can_change[i + idx] && ans[i + idx] != s[i]) {
return false;
}
}
return true;
}

void change_last2b(string& ans, int idx, const string& s) {
bool is_last = true;
for (int i = m - 1; i >= 0; i--) {
if (can_change[i + idx]) {
if (is_last) {
ans[i + idx] = 'b';
is_last = false;
can_change[i + idx] = false;
} else {
ans[i + idx] = 'a';
}
}
}
}

void set_all_a(string& ans, int idx, const string& s) {
for (int i = 0; i < m; i++) {
if (can_change[i + idx]) {
ans[i + idx] = 'a';
}
}
}
public:
string generateString(const string& str1, const string& str2) {
n = str1.size();
m = str2.size();
string ans(n + m - 1, '-');
can_change = move(vector<bool>(n + m - 1, true));

for (int i = 0; i < str1.size(); i++) {
if (str1[i] == 'T') {
if (!fillT(ans, i, str2)) {
return "";
}
}
}

for (int i = 0; i < str1.size(); i++) {
if (str1[i] == 'F') {
if (!fillF(ans, i, str2)) {
return "";
}
}
}

return ans;
}
};

#ifdef _DEBUG
/*
TFTF
ab

ababa
*/
/*
FT
aghbdfhf

aaghbdfhf
*/
int main() {
string a, b;
while (cin >> a >> b) {
Solution sol;
cout << sol.generateString(a, b) << endl;
}
return 0;
}
#endif

同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~

千篇源码题解已开源


3474.字典序最小的生成字符串:暴力填充
https://blog.letmefly.xyz/2026/03/31/LeetCode 3474.字典序最小的生成字符串/
作者
发布于
2026年3月31日
许可协议