【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;
}
相关推荐
偷偷的卷13 小时前
【算法笔记 11】贪心策略六
笔记·算法
小冯的编程学习之路13 小时前
【C++】: C++基于微服务的即时通讯系统(1)
开发语言·c++·微服务
ZPC821013 小时前
FPGA 部署ONNX
人工智能·python·算法·机器人
_w_z_j_14 小时前
爱丽丝的人偶
算法
老前端的功夫14 小时前
Vue2中key的深度解析:Diff算法的性能优化之道
前端·javascript·vue.js·算法·性能优化
淀粉肠kk14 小时前
【C++】map和set的使用
c++
yongui4783415 小时前
基于深度随机森林(Deep Forest)的分类算法实现
算法·随机森林·分类
是苏浙15 小时前
零基础入门C语言之C语言实现数据结构之单链表经典算法
c语言·开发语言·数据结构·算法
纵有疾風起15 小时前
C++—vector:vecor使用及模拟实现
开发语言·c++·经验分享·开源·stl·vector
橘颂TA15 小时前
【剑斩OFFER】算法的暴力美学——点名
数据结构·算法·leetcode·c/c++