【字符串】【 LCP】【C++算法】2573找出对应 LCP 矩阵的字符串

简介: 【字符串】【 LCP】【C++算法】2573找出对应 LCP 矩阵的字符串

作者推荐

【深度优先搜索】【树】【有向图】【推荐】685. 冗余连接 II

本文涉及知识点

字符串 LCP

LeetCode:2573找出对应 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

LPC

word串 如果有m个不同字符,则一定是[‘a’+0,‘a’+m) 。否则换成更小的字符,字典序更小。

如果存在合法串,则word[0]一定是a,如果lcp[0][x] >=1 ,则word[x]也是’a’

word中第一个未处理的字符是’b’⋯ \cdots

⋯ \cdots

如果用到第27个字符,则非法。

最后将结果串求lcp,看是否一致,不一致,也返回非法。

代码

核心代码

//最长公共前缀(Longest Common Prefix)
class CLCP
{
public:
  CLCP(const string& str1, const string& str2)
  {
    m_dp.assign(str1.length() , vector<int>(str2.length()));
    //str1[j...)和str2[k...]比较时, j和k不断自增,总有一个先到达末端
    for (int i = 0; i < str1.length(); i++)
    {//枚举str2 先到末端 str1[i]和str2.back对应
      m_dp[i][str2.length() - 1] = (str1[i] == str2.back());
      for (int j = i-1 ; j >= 0 ; j-- )
      {
        const int k = str2.length() - 1 - (i-j);
        if (k < 0)
        {
          break;
        }
        if (str1[j] == str2[k])
        {
          m_dp[j][k] = 1 + m_dp[j + 1][k + 1];
        }
      }     
    }
    for (int i = 0; i < str2.length(); i++)
    {//枚举str1 先到末端 str2[i]和str1.back对应
      m_dp[str1.length()-1][i] = (str1.back() == str2[i]);
      for (int j = i - 1; j >= 0; j--)
      {
        const int k = str1.length() - 1 - (i-j);
        if (k < 0)
        {
          break;
        }
        if (str1[k] == str2[j])
        {
          m_dp[k][j] = 1 + m_dp[k + 1][j + 1];
        }
      }
    }
  }
  vector<vector<int>> m_dp;
};
class Solution {
public:
  string findTheString(vector<vector<int>>& lcp) {
    const int n = lcp.size();
    string word(n, ' ');
    for (int i = 0; ; i++)
    {
      int iPos = word.find(' ');
      if (-1 == iPos)
      {
        break;
      }
      if (i >= 26)
      {
        return "";
      }
      for (int j = iPos ; j < n; j++)
      {
        if (lcp[iPos][j] >= 1)
        {
          word[j] = 'a' + i;
        }
      }
    }
    CLCP lcpHlp(word, word);
    for (int i = 0; i < n; i++)
    {
      for (int j = 0; j < n; j++)
      {
        if (lcp[i][j] != lcpHlp.m_dp[i][j])
        {
          return "";
        }
      }
    }
    return word;
  }
};

测试用例

template<class T,class T2>
void Assert(const T& t1, const T2& t2)
{
  assert(t1 == t2);
}
template<class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{
  if (v1.size() != v2.size())
  {
    assert(false);
    return;
  }
  for (int i = 0; i < v1.size(); i++)
  {
    Assert(v1[i], v2[i]);
  }
}
int main()
{ 
  vector<vector<int>> lcp;
  {
    Solution sln;
    lcp = { {4,0,2,0},{0,3,0,1},{2,0,2,0},{0,1,0,1} };
    auto res = sln.findTheString(lcp);
    Assert(res,"abab");
  }
  {
    Solution sln;
    lcp = { {4,3,2,1},{3,3,2,1},{2,2,2,1},{1,1,1,1} };
    auto res = sln.findTheString(lcp);
    Assert(res, "aaaa");
  }
  {
    Solution sln;
    lcp = { {4,3,2,1},{3,3,2,1},{2,2,2,1},{1,1,1,3} };
    auto res = sln.findTheString(lcp);
    Assert(res, "");
  }
    
}

2023 年5月

class Solution {

public:

string findTheString(vector<vector>& lcp) {

char ch = ‘a’;

m_c = lcp.size();

string str(m_c, ‘#’);

for (int i = 0; i < m_c; i++)

{

if (‘#’ != str[i])

{

continue;

}

if (ch > ‘z’)

{

return “”;

}

for (int j = 0; j < m_c; j++)

{

if (lcp[i][j] > 0)

{

if (‘#’ != str[j])

{

return “”;

}

str[j] = ch;

}

}

ch++;

}

if (!Check(str, lcp))

{

return “”;

}

return str;

}

bool Check(const string& str, vector<vector>& lcp)

{

for (int r = m_c - 1; r >= 0; r–)

{

int iNum = 0;

for (int j = m_c-1,i = r ; (i>=0) && (j>=0) ; j–,i–)

{

if (str[i] == str[j])

{

iNum++;

}

else

{

iNum = 0;

}

if (lcp[i][j] != iNum)

{

return false;

}

if (lcp[i][j] != lcp[j][i])

{

return false;

}

}

}

return true;

}

int m_c;

};


相关文章
|
5天前
|
算法 搜索推荐 程序员
第六十五练 字符串匹配 - Rabin-Karp算法
第六十五练 字符串匹配 - Rabin-Karp算法
6 1
|
5天前
|
算法 搜索推荐 程序员
第六十四练 字符串匹配 - Boyer-Moore算法
第六十四练 字符串匹配 - Boyer-Moore算法
8 0
|
5天前
|
算法 搜索推荐 程序员
第六十三练 字符串匹配 - KMP算法
第六十三练 字符串匹配 - KMP算法
8 2
|
5天前
|
算法 C语言 人工智能
|
5天前
|
算法
【免费】面向多微网网络结构设计的大规模二进制矩阵优化算法
【免费】面向多微网网络结构设计的大规模二进制矩阵优化算法
|
5天前
|
编解码 JavaScript 前端开发
【专栏】介绍了字符串Base64编解码的基本原理和在Java、Python、C++、JavaScript及Go等编程语言中的实现示例
【4月更文挑战第29天】本文介绍了字符串Base64编解码的基本原理和在Java、Python、C++、JavaScript及Go等编程语言中的实现示例。Base64编码将24位二进制数据转换为32位可打印字符,用“=”作填充。文中展示了各语言的编码解码代码,帮助开发者理解并应用于实际项目。
|
5天前
|
存储 编译器 C语言
C++字符串大小写之for语句
C++字符串大小写之for语句
20 0
|
5天前
|
存储 缓存 算法
C++从入门到精通:4.6性能优化——深入理解算法与内存优化
C++从入门到精通:4.6性能优化——深入理解算法与内存优化
|
5天前
|
算法 数据安全/隐私保护 计算机视觉
基于二维CS-SCHT变换和LABS方法的水印嵌入和提取算法matlab仿真
该内容包括一个算法的运行展示和详细步骤,使用了MATLAB2022a。算法涉及水印嵌入和提取,利用LAB色彩空间可能用于隐藏水印。水印通过二维CS-SCHT变换、低频系数处理和特定解码策略来提取。代码段展示了水印置乱、图像处理(如噪声、旋转、剪切等攻击)以及水印的逆置乱和提取过程。最后,计算并保存了比特率,用于评估水印的稳健性。
|
2天前
|
算法
m基于BP译码算法的LDPC编译码matlab误码率仿真,对比不同的码长
MATLAB 2022a仿真实现了LDPC码的性能分析,展示了不同码长对纠错能力的影响。短码长LDPC码收敛快但纠错能力有限,长码长则提供更强纠错能力但易陷入局部最优。核心代码通过循环进行误码率仿真,根据EsN0计算误比特率,并保存不同码长(12-768)的结果数据。
20 9
m基于BP译码算法的LDPC编译码matlab误码率仿真,对比不同的码长