动态规划方法:
首先使用二维数组dp,确定其元素dp[i][j]的含义(此处指str1的第i个元素和str2的第j个元素为结尾的最长公共子串长度,注意最后一个元素必然是相同的)。
然后找到状态转移方程:若新加入元素相同,则在原长度加一,即dp[i][j]=dp[i-1][j-1]+1,否则为0。接着考虑dp数组的初始化即边界条件。
最后由于要返回最长公共子串序列,而dp数组只记录了其长度数值,故需要确定最大长度,即dp数组最大值,以及公共子串的结尾标志,通过结尾标志和子串长度回到原字符串中寻找公共子串。
class Solution {
public:
/**
* longest common substring
* @param str1 string字符串 the string
* @param str2 string字符串 the string
* @return string字符串
*/
string LCS(string str1, string str2) {
// write code here
//使用二维数组
/*
int maxLen=0;
int maxLastind=0;
int dp[str1.length()][str2.length()];
dp[0][0]=0;//初始化
for(int i=0;i<str1.length();++i)
{
for(int j=0;j<str2.length();++j)
{
if(str1[i]==str2[j])
{
if(i==0 || j==0)
{//边界条件
dp[i][j]=1;
}
else
{//状态转移方程
dp[i][j]=dp[i-1][j-1]+1;
if(dp[i][j]>maxLen)
{//确定最长公共子串的长度与结束标志
maxLen=dp[i][j];
maxLastind=i;
}
}
}
else
dp[i][j]=0;
}
}
return str1.substr(maxLastind-maxLen+1,maxLen);
*/
//优化:使用一维数组
int maxLen=0;
int maxLastind=0;
vector<int> dp(str2.length(),0);
for(int i=0;i<str1.length();++i)
{
for(int j=str2.length()-1;j>=0;--j)
{//注意必须是倒序,因为原本需要用到左上角元素值,故从右往左进行
if(str1[i]==str2[j])
{
if(i==0 || j==0)
{
dp[j]=1;
}
else
{
dp[j]=dp[j-1]+1;
if(dp[j]>maxLen)
{
maxLen=dp[j];
maxLastind=j;
}
}
}
else
dp[j]=0;
}
}
return str2.substr(maxLastind-maxLen+1,maxLen);
}
}; 


京公网安备 11010502036488号