【字符串】【 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;

};


相关文章
|
17天前
|
机器学习/深度学习 安全 算法
【图论】【割点】【C++算法】928. 尽量减少恶意软件的传播 II
【图论】【割点】【C++算法】928. 尽量减少恶意软件的传播 II
|
存储 编译器 Linux
标准库中的string类(中)+仅仅反转字母+字符串中的第一个唯一字符+字符串相加——“C++”“Leetcode每日一题”
标准库中的string类(中)+仅仅反转字母+字符串中的第一个唯一字符+字符串相加——“C++”“Leetcode每日一题”
|
11天前
|
安全 C++
石头剪子布(字符串解法 C++)
石头剪子布(字符串解法 C++)
17 0
|
17天前
|
算法 测试技术 C#
【广度优先搜索】【堆】【C++算法】407. 接雨水 II
【广度优先搜索】【堆】【C++算法】407. 接雨水 II
|
17天前
|
算法 测试技术 Serverless
【二分查找】【C++算法】378. 有序矩阵中第 K 小的元素
【二分查找】【C++算法】378. 有序矩阵中第 K 小的元素
|
17天前
|
算法 测试技术 C#
【字典树】【KMP】【C++算法】3045统计前后缀下标对 II
【字典树】【KMP】【C++算法】3045统计前后缀下标对 II
|
1月前
|
传感器 算法 计算机视觉
基于肤色模型和中值滤波的手部检测算法FPGA实现,包括tb测试文件和MATLAB辅助验证
该内容是关于一个基于肤色模型和中值滤波的手部检测算法的描述,包括算法的运行效果图和所使用的软件版本(matlab2022a, vivado2019.2)。算法分为肤色分割和中值滤波两步,其中肤色模型在YCbCr色彩空间定义,中值滤波用于去除噪声。提供了一段核心程序代码,用于处理图像数据并在FPGA上实现。最终,检测结果输出到&quot;hand.txt&quot;文件。
|
1月前
|
机器学习/深度学习 算法 计算机视觉
基于yolov2深度学习网络的视频手部检测算法matlab仿真
基于yolov2深度学习网络的视频手部检测算法matlab仿真
|
1月前
|
算法
【MATLAB】语音信号识别与处理:移动中位数滤波算法去噪及谱相减算法呈现频谱
【MATLAB】语音信号识别与处理:移动中位数滤波算法去噪及谱相减算法呈现频谱
23 2
|
1月前
|
算法
【MATLAB】语音信号识别与处理:一维信号NLM非局部均值滤波算法去噪及谱相减算法呈现频谱
【MATLAB】语音信号识别与处理:一维信号NLM非局部均值滤波算法去噪及谱相减算法呈现频谱
40 1