【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 。如果不存在这样的字符串,则返回空字符串。

对于长度相同的两个字符串 a 和 b ,如果在 a 和 b 不同的第一个位置,字符串 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,我们尝试选择 a 到 z 中的每个字符,并检查它是否满足矩阵 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;
}
相关推荐
行者全栈架构师5 分钟前
【鸿蒙心迹】鸿蒙网络请求架构实战——@ohos.net.http 到 Axios 封装、拦截器与统一错误处理(HarmonyOS 7.x)
前端·算法·架构
Tri_Function9 分钟前
背包:从入门到实战
c++
j7~18 分钟前
【C++ 标准项目】发布订阅消息队列 (篇七):项目创建与基础工具模块搭建
开发语言·c++·log4j·uuid·protobuf·helper工具·消息定义类型和交换机类型定义
小宋102119 分钟前
OpenTelemetry GenAI可观测性实战:串起模型、工具、Token与错误
java·人工智能·算法·贪心算法
嫂子开门我是_我哥21 分钟前
青少年抑郁、焦虑、失眠与自杀相关表现的症状联系:一篇网络分析论文所使用的算法深度解读
论文阅读·算法·论文笔记
渊鱼L32 分钟前
CAD随机颗粒插件2D V2.0 更新说明
算法
Lazionr33 分钟前
unordered_map和unordered_set的使用
开发语言·c++·算法
行者全栈架构师39 分钟前
从 55% 到 6%:一个快餐营养规划器的算法迭代实录
后端·算法·架构
进化中的刀盾兽1 小时前
从零实现 C++ Json-Rpc(九):从 TCP 字节流中拆出完整消息——MuduoBuffer 与 LVProtocol
c++·rpc
Laurie三省1 小时前
现场版却配上录音室版的歌词?聊聊我给开源 Mac 歌词软件写的多源打分算法
算法·macos·go