LeetCode 3302.字典序最小的合法序列

给你两个字符串 word1 和 word2 。

如果一个字符串 x 修改 至多 一个字符会变成 y ,那么我们称它与 y 几乎相等 。

如果一个下标序列 seq 满足以下条件,我们称它是 合法的 :

下标序列是 升序 的。

将 word1 中这些下标对应的字符 按顺序 连接,得到一个与 word2 几乎相等 的字符串。

请你返回一个长度为 word2.length 的数组,表示一个 字典序最小 的 合法 下标序列。如果不存在这样的序列,请你返回一个 空 数组。

注意 ,答案数组必须是字典序最小的下标数组,而 不是 由这些下标连接形成的字符串。

示例 1:

输入:word1 = "vbcca", word2 = "abc"

输出:0,1,2

解释:

字典序最小的合法下标序列为 0, 1, 2

将 word10 变为 'a' 。

word11 已经是 'b' 。

word12 已经是 'c' 。

示例 2:

输入:word1 = "bacdc", word2 = "abc"

输出:1,2,4

解释:

字典序最小的合法下标序列为 1, 2, 4

word11 已经是 'a' 。

将 word12 变为 'b' 。

word14 已经是 'c' 。

示例 3:

输入:word1 = "aaaaaa", word2 = "aaabc"

输出:\[\]

解释:

没有合法的下标序列。

示例 4:

输入:word1 = "abc", word2 = "ab"

输出:0,1

提示:

1 <= word2.length < word1.length <= 3 * 105^55

word1 和 word2 只包含小写英文字母。

我们需要找到下标的字典序最小的合法序列,因此在对word1和word2进行匹配时,如果两个字符相等,那么一定要匹配上,这样才能保证下标的字典序最小;否则两个字符不等时,如果把当前word1中的字符修改为word2中的字符后,后面如果两个字符串还能匹配上,则需要把当前字符加入答案数组,如何知道后面两个字符串是否还能匹配上,可以使用后缀数组,我们先反向遍历word1和word2,找出word1的后缀能匹配到的最长word2后缀,然后用数组把每个word1下标对应的能匹配到的最长word2后缀的开始位置记录下来:

cpp 复制代码
class Solution {
public:
    vector<int> validSequence(string word1, string word2) {
        int size1 = word1.size();
        int size2 = word2.size();

        vector<int> suf(size1 + 1);
        suf[size1] = size2;

        int idx1 = size1 - 1;
        int idx2 = size2 - 1;

        while (idx1 >= 0 && idx2 >= 0) {
            if (word1[idx1] == word2[idx2]) {
                --idx2;
            }

            // word1的idx1下标最多能匹配到word2[idx2 + 1, word2.size()]
            suf[idx1] = idx2 + 1;
            --idx1;
        }

        while (idx1 >= 0) {
            suf[idx1] = idx2 + 1;
            --idx1;
        }

        vector<int> ans(size2);

        idx1 = 0;
        idx2 = 0;

        bool hasChanged = false;

        while (idx1 < size1 && idx2 < size2) {
            // 如果能匹配到
            // 或没有改变过,且改变后可以匹配成功
            // 则将idx1加入结果数组
            if (word1[idx1] == word2[idx2] || 
                !hasChanged && suf[idx1 + 1] <= idx2 + 1) {
   
                if (word1[idx1] != word2[idx2]) {
                    hasChanged = true;
                }

                ans[idx2] = idx1;

                ++idx1;
                ++idx2;
            } else {
                ++idx1;
            }

            // 找到目标长度的答案
            if (idx2 == size2) {
                return ans;
            }
        }

        return {};
    }
};

如果word1的长度为n,则此算法时间复杂度为O(n),空间复杂度为O(n)。

相关推荐
8Qi84 小时前
回文子串(Palindromic Substrings)—— 题解
算法·leetcode·职场和发展·动态规划
小欣加油9 小时前
leetcode1926 迷宫中离入口最近的出口
数据结构·c++·算法·leetcode·职场和发展
兰令水17 小时前
leecodecode【区间DP+树形DP】【2026.6.10打卡-java版本】
java·算法·leetcode
8Qi818 小时前
LeetCode 4:寻找两个正序数组的中位数 —— 二分查找法
java·算法·leetcode·职场和发展·二分查找
8Qi818 小时前
LeetCode 32:最长有效括号 —— 栈 + 标记法 题解
java·数据结构·算法·leetcode·职场和发展··括号匹配
Tairitsu_H18 小时前
[LC优选算法#3] 滑动窗口 | 将x减到0的最⼩操作数 | ⽔果成篮 | 字⺟异位词
c++·算法·leetcode·滑动窗口
洛水水19 小时前
【力扣100题】76.搜索插入位置
数据结构·算法·leetcode
wabs66620 小时前
关于动态规划【力扣343.整数拆分的递推公式怎么理解?】
算法·leetcode·动态规划
承渊政道21 小时前
【MySQL数据库学习】MySQL基本查询(下)
数据库·学习·mysql·leetcode·bash·数据库开发·数据库系统
洛水水1 天前
【力扣100题】78.在排序数组中查找元素的第一个和最后一个位置
数据结构·算法·leetcode