问题:
计算两个字符串的最大公共子串(longest common continue substring),
注意不是子序列是子串,子串是要求字符之间是相连的,而序列则只要求是保持前后顺序不变.
我们这里要求的是最长公共子串的长度.
思想:
设:C[i,j] = LCS(str1[1...i],str2[1...j]),
即C[i,j]表示序列str1[1...i]和str2[1...j]的最长公共子序列的长度,则 C[m,n] = LCS(str1,str2)就是问题的解(长度为m,n).
计算公式为:
if str1[i] == str2[j] then C[i,j] = C[i-1,j-1] +1;
else if str1[i] != str2[j] then C[i,j] =0.
代码:
完整代码已上传我的github,项目名DP,其中还有最大公共子序列和最长回文子串的实现:https://github.com/yisun03/DP
LCS_CTN.h
//
// Created by yis on 2020/7/12.
//
#ifndef DYNAMIC_PROGRAMMING_LCS_CTN_H
#define DYNAMIC_PROGRAMMING_LCS_CTN_H
#include <string>
#include <vector>
using std::string;
using std::vector;
namespace yis
{
class LCS_CTN
{
// 计算两个字符串的最大公共子串(longest common continue substring),
// 注意不是子序列是子串,子串是要求字符之间是相连的,而序列则只要求是保持前后顺序不变.
// 我们这里要求的是最长公共子串的长度.
public:
// 计算两个字符串的最长公共子串(连续子序列).
// 计算公式为:
// if str1[i] == str2[j] then C[i,j] = C[i-1,j-1] +1;
// else if str1[i] != str2[j] then C[i,j] = 0.
static int lcs_continue(string& str1, string& str2, int m, int n);
};
}
#endif //DYNAMIC_PROGRAMMING_LCS_CTN_H
LCS_CTN.cpp
//
// Created by yis on 2020/7/12.
//
#include "LCS_CTN.h"
namespace yis
{
int LCS_CTN::lcs_continue(string &str1, string &str2 ,int m, int n)
{
int biggest = 0;
vector<vector<int>> dp_table(m+1,vector<int>(n+1));
for(int i = 0; i < m+1; ++i)
{
for(int j = 0; j < n+1; ++j)
{
if(i == 0 || j == 0)
{
dp_table[i][j] = 0;
}
else if(str1[i-1] == str2[j-1])
{
dp_table[i][j] = dp_table[i-1][j-1] +1;
biggest = dp_table[i][j] > biggest ? dp_table[i][j] : biggest;
}
else
{
dp_table[i][j] = 0;
}
}
}
return biggest;
}
}
main.cpp
//
// Created by yis on 2020/7/12.
//
#include <iostream>
#include "LCS_CTN.h"
int main()
{
string str3 = "asdfas";
string str4 = "werasdfaswer";
std::cout << "str3 和str4的最长公共子串为:\n" << yis::LCS_CTN::lcs_continue(str3,str4,str3.length(),str4.length());
std::cout << std::endl;
return 0;
}
实验结果: