2019年大疆测试开发岗唯一一道编程题就是最长公共子串问题,看了一下,还有个常见的问题是最长公共子序列问题,今天一并总结一下。
最长公共子序列
1.牛客网地址 [可以全通过]
Ctrl/Cmd + K www.nowcoder.com/practice/47…
2.问题
给定两个字符串str1和str2,返回两个字符串的最长公共子序列,例如:
str1="1A2C3D4B56" ,str2="B1D23CA45B6A"
"123456"和"12C4B6"都是最长公共子序列,返回哪一个都行。
输入:
1A2C3D4B56
B1D23CA45B6A
输出:123456
注:"123456"和“12C4B6”都是最长公共子序列,任意输出一个。
3.代码
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
#define M 10000
#define N 10000
int dp[M][N];
string findTheLongestSameStr(string str1, string str2, int len1, int len2)
{
string result;
if (len1 == 0 || len2 == 0)
return result;
int m = len1 + 1;
int n = len2 + 1;
//初始化
for (int i = 0; i < m; i++)
dp[i][0] = 0;
for (int j = 0; j < n; j++)
dp[0][j] = 0;
//填满矩阵
for (int i = 1; i < m; i++)
for (int j = 1; j < n; j++)
{
if (str1[i - 1] == str2[j - 1])
dp[i][j] = dp[i - 1][j - 1] + 1;
else
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
}
//cout << dp[m - 1][n - 1] << endl;//输出最长公共子序列长度
//找到最长公共子序列
for (int i = m - 1, j = n - 1; (i > 0) && (j > 0); )
{
if (str1[i - 1] == str2[j - 1])
{
result = str1[i - 1] + result;
i--;
j--;
}
else if (dp[i - 1][j] > dp[i][j - 1])
i--;
else
j--;
}
return result;
}
int main()
{
string str1, str2;
getline(cin, str1);
getline(cin, str2);
int len1 = str1.size();
int len2 = str2.size();
string result = findTheLongestSameStr(str1, str2, len1, len2);
cout << result << endl;
return 0;
}
最长公共子串
1.牛客网地址[只通过了部分就内存超了]
Ctrl/Cmd + K www.nowcoder.com/practice/21…
2.问题
有两个字符串str和str2,求出两个字符串中最长公共子串长度。
比如:str=acbcbcef,str2=abcbced,则str和str2的最长公共子串为bcbce,最长公共子串长度为5
3.思路
初步:
(1)分别以两个字符为行和列构造矩阵dp[i][j]
(2)若str1[i]==str2[j],dp[i][j]=1,否则为0
(3)通过查找值为1的最长对角线即可找到最长公共子串
Ctrl/Cmd + Shift + I
升级:
(1)将dp规模为len1,len2
(2)若str1[i]==str2[j],dp[i][j]=dp[i-1][j-1]+1,否则为0
(3)dp[i][j]的最大值就是最长公共子序列长度max,最长公共子序列为str2.substr(jmax-max , max)
Ctrl/Cmd + Shift + I
4.代码
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
#define M 100
#define N 100
int dp[M][N];
void findTheMaxSameStr(string str1, string str2)
{
int len1 = str1.size();
int len2 = str2.size();
int m = len1 + 1;
int n = len2 + 1;
string result;
if (len1 == 0 || len2 == 0)
{
cout << result <<endl;
return;
}
//填充dp矩阵
int max=0, imax=0, jmax=0;
for(int i=1; i<m ;i++)
for (int j = 1; j < n; j++)
{
if (str1[i - 1] == str2[j - 1])
{
dp[i][j] = dp[i - 1][j - 1] + 1;
if (dp[i][j] > max)
{
max = dp[i][j];
imax = i;
jmax = j;
}
}
}
cout << max << endl;
result = str2.substr(jmax-max, max);
cout << result << endl;
return;
}
int main()
{
string str1, str2;
getline(cin, str1);
getline(cin, str2);
memset(dp, 0, sizeof(dp));
findTheMaxSameStr(str1, str2);
return 0;
}