【3.10】贪心算法-找出对应 LCP 矩阵的字符串

一、题目

对任一由 n 个小写英文字母组成的字符串 word ,我们可以定义一个 n x n 的矩阵,并满足:

  • lcp[i][j] 等于子字符串 word[i,...,n-1]word[j,...,n-1] 之间的最长公共前缀的长度。

给你一个 n x n 的矩阵 lcp 。返回与 lcp 对应的、按字典序最小的字符串 word 。如果不存在这样的字符串,则返回空字符串。

对于长度相同的两个字符串 ab ,如果在 ab 不同的第一个位置,字符串 a 的字母在字母表中出现的顺序先于 b 中的对应字母,则认为字符串 a 按字典序比字符串 b 小。例如,"aabd" 在字典上小于 "aaca" ,因为二者不同的第一位置是第三个字母,而 'b' 先于 'c' 出现。

示例 1:

复制代码
输入:lcp = [[4,0,2,0],[0,3,0,1],[2,0,2,0],[0,1,0,1]]
输出:"abab"
解释:lcp 对应由两个交替字母组成的任意 4 字母字符串,字典序最小的是 "abab" 。

示例 2:

复制代码
输入:lcp = [[4,3,2,1],[3,3,2,1],[2,2,2,1],[1,1,1,1]]
输出:"aaaa"
解释:lcp 对应只有一个不同字母的任意 4 字母字符串,字典序最小的是 "aaaa" 。 

示例 3:

复制代码
输入:lcp = [[4,3,2,1],[3,3,2,1],[2,2,2,1],[1,1,1,3]]
输出:""
解释:lcp[3][3] 无法等于 3 ,因为 word[3,...,3] 仅由单个字母组成;因此,不存在答案。

提示:

  • 1 <= n == ``lcp.length == ``lcp[i].length <= 1000
  • 0 <= lcp[i][j] <= n

二、解题思路

要解决这个问题,我们可以使用贪心算法的思路来逐步构建字符串 word。贪心算法的核心思想是在每一步选择中都采取当前状态下最好或最优(即最有利)的选择,从而希望导致结果是全局最好或最优的。

具体步骤如下:

  1. 初始化字符串 :从第一个字符开始,逐步构建字符串 word

  2. 选择字符 :对于每个位置 i,我们需要选择一个字符 word[i],使得它与之前的字符串 word[0:i] 和矩阵 lcp 中的信息一致,并且按字典序最小。

  3. 验证 :选择字符后,验证它是否满足矩阵 lcp 中的信息。如果不满足,则返回空字符串。

  4. 迭代:继续选择下一个字符,直到构造完整个字符串。

具体的贪心策略如下:

  • 对于每个位置 i,我们尝试选择 az 中的每个字符,并检查它是否满足矩阵 lcp 中的信息。

  • 选择满足条件且按字典序最小的字符。

三、代码实现

cpp 复制代码
#include <iostream>
#include <vector>
#include <string>

using namespace std;

string findTheString(vector<vector<int>>& lcp) {
    int n = lcp.size();
    string word(n, ' ');

    for (int i = 0; i < n; ++i) {
        for (char c = 'a'; c <= 'z'; ++c) {
            word[i] = c;
            bool valid = true;
            for (int j = 0; j <= i; ++j) {
                int prefix_len = 0;
                while (i + prefix_len < n && j + prefix_len < n && word[i + prefix_len] == word[j + prefix_len]) {
                    ++prefix_len;
                }
                if (lcp[i][j] != prefix_len || lcp[i][j] != lcp[j][i]) {
                    valid = false;
                    break;
                }
            }
            if (valid) {
                break;
            }
        }
        if (!valid) {
            return "";
        }
    }

    return word;
}

int main() {
    vector<vector<int>> lcp1 = {{4, 0, 2, 0}, {0, 3, 0, 1}, {2, 0, 2, 0}, {0, 1, 0, 1}};
    cout << findTheString(lcp1) << endl;  // 输出: "abab"

    return 0;
}
相关推荐
冠位观测者21 分钟前
【Leetcode 每日一题 - 补卡】1534. 统计好三元组
数据结构·算法·leetcode
明月看潮生26 分钟前
青少年编程与数学 02-016 Python数据结构与算法 25课题、量子算法
python·算法·青少年编程·量子计算·编程与数学
weixin_4450547233 分钟前
力扣刷题-热题100题-第35题(c++、python)
c++·python·leetcode
XXYBMOOO34 分钟前
基于 Qt 的 BMP 图像数据存取至 SQLite 数据库的实现
数据库·c++·qt
JNU freshman1 小时前
C. Robin Hood in Town思考与理解
算法
虾球xz1 小时前
游戏引擎学习第230天
c++·学习·游戏引擎
_x_w2 小时前
【17】数据结构之图及图的存储篇章
数据结构·python·算法·链表·排序算法·图论
anscos2 小时前
Actran声源识别方法连载(二):薄膜模态表面振动识别
人工智能·算法·仿真软件·actran
-优势在我2 小时前
LeetCode之两数之和
算法·leetcode
WaitWaitWait012 小时前
LeetCode每日一题4.17
算法·leetcode