/***********************************************************************
*description:最长公共子串
* 给定两个字符串str1和str2,返回两个字符串的最长公共子串
* 如:str1=“1AB2345CD” str2=“12345EF”
* 返回“2345”
*description:最长公共子串
* 给定两个字符串str1和str2,返回两个字符串的最长公共子串
* 如:str1=“1AB2345CD” str2=“12345EF”
* 返回“2345”
***********************************************************************/
#include <iostream>
#include <string>
#include <vector>
using namespace std;
//方法1:时间复杂度O(M*N),空间复杂度O(M*N)
//经典动态规划问题,数组dp[M][N]
//dp[i][j]代表str1[i]和str2[j]当做公共子串最后元素的最大长度
//dp[i][0]:str1[i]==str2[0]时才为1,否则为0
//dp[0][j]:str1[0]==str2[j]时才为1,否则为0
//dp[i][j]:
// 1.str1[i]!=str2[j],dp[i][j]=0
// 2.str1[i]==str2[j],dp[i][j]=dp[i-1][j-1]+1
//得到dp之后,遍历找到最大的元素及其位置,然后str1的该位置向前索引即可。
string longestSharedSubStr_1(string str1, string str2)
{
string res;
int M = str1.size();
int N = str2.size();
if (M == 0 || N == 0)
return res;
vector<vector<int>> dp(M,N);
for (int i = 0; i < M; i++)
{
dp[i][0] = 0;
if (str1[i] == str2[0])
dp[i][0] = 1;
}
for (int j = 0; j < N; j++)
{
dp[0][j] = 0;
if (str1[0] == str2[j])
dp[0][j] = 1;
}
for (int i = 1; i < M; i++)
{
for (int j = 1; j < N; j++)
{
if (str1[i] != str2[j])
dp[i][j] = 0;
else
dp[i][j] = dp[i-1][j-1] + 1;
}
}
int len = 0;
int endIdx = 0;
for (int i = 0; i < M - 1; i++)
{
for (int j = 0; j < N; j++)
{
if (dp[i][j] > len)
{
len = dp[i][j];
endIdx = i;
}
}
}
return str1.substr(endIdx - len + 1, len);
}
//方法2:时间复杂度O(M*N),空间复杂度O(1)
//在方法1的基础上进行优化。
//每次计算dp[i][j]时,只和dp[i-1][j-1]相关,所以每次按斜线计算,只用一个变量空间。
//然后用个全局变量记录len和endIdx
string longestSharedSubStr_2(string str1, string str2)
{
int M = str1.size();
int N = str2.size();
if (M == 0 || N == 0)
return "";
int len = 0;
int endIdx = 0;
int last = 0;
int col = N -1;
int row = 0;
while (row < M)
{
last = 0;
int i = row;
int j = col;
while (i < M && j < N)
{
if (str1[i] == str2[j])
{
last++;
}
if (last > len )
{
len = last;
endIdx = i;
}
i++;
j++;
}
if (col > 0)
col--;
else
row++;
}
return str1.substr(endIdx - len + 1, len);
}
int main()
{
string str1 = "1AB2345CD";
string str2 = "12345EF";
cout << longestSharedSubStr_2(str1, str2);
return 0;
}