LeetCode 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 n+m-1 n+m−1的答案字符串,然后开始填充这个字符串。使用一个布尔类型的数组记录每个字符是否还可以被修改。

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

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

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

接下来填充F

若从F位置开始接下来 m m 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 ( n m ) O(nm) O(nm)
  • 空间复杂度 O ( n + m ) O(n+m) O(n+m)

AC代码

C++
cpp 复制代码
/*
 * @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和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~

千篇源码题解已开源

相关推荐
Alicx.2 小时前
map容器是个好东西
数据结构·算法·蓝桥杯
郝学胜-神的一滴2 小时前
张量维度操控心法:从reshape到升维降维,吃透PyTorch形状操作的底层逻辑
人工智能·pytorch·python·深度学习·程序人生·算法·机器学习
老虎06272 小时前
LeetCode热题100 刷题笔记(第五天)多维动态规划(中心扩展法) 「 最长回文子串」
笔记·leetcode·动态规划
果果燕2 小时前
ARM嵌入式学习(四)--- C语言应用:led、beep、key
linux·运维·算法
Q741_1472 小时前
每日一题 力扣 2751.机器人碰撞 映射 模拟 栈 C++ 题解
算法·leetcode·模拟··映射
源码之家2 小时前
计算机毕业设计:基于Python的二手车数据分析可视化系统 Flask框架 可视化 时间序列预测算法 逻辑回归 requests 爬虫 大数据(建议收藏)✅
大数据·hadoop·python·算法·数据分析·flask·课程设计
liuyao_xianhui3 小时前
优选算法_岛屿数量_floodfill算法)_bfs_C++
java·开发语言·数据结构·c++·算法·链表·宽度优先
羊小蜜.3 小时前
Mysql 04: 子查询——5 大核心用法
数据库·mysql·算法·子查询
深邃-3 小时前
字符函数和字符串函数(2)
c语言·数据结构·c++·后端·算法·restful