一、题目
对任一由 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<= 10000 <= lcp[i][j] <= n
二、解题思路
要解决这个问题,我们可以使用贪心算法的思路来逐步构建字符串 word。贪心算法的核心思想是在每一步选择中都采取当前状态下最好或最优(即最有利)的选择,从而希望导致结果是全局最好或最优的。
具体步骤如下:
-
初始化字符串:从第一个字符开始,逐步构建字符串
word。 -
选择字符:对于每个位置
i,我们需要选择一个字符word[i],使得它与之前的字符串word[0:i]和矩阵lcp中的信息一致,并且按字典序最小。 -
验证:选择字符后,验证它是否满足矩阵
lcp中的信息。如果不满足,则返回空字符串。 -
迭代:继续选择下一个字符,直到构造完整个字符串。
具体的贪心策略如下:
-
对于每个位置
i,我们尝试选择a到z中的每个字符,并检查它是否满足矩阵lcp中的信息。 -
选择满足条件且按字典序最小的字符。
三、代码实现
#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;
}









