题目
注意:两个字符串的最长公共子串(DP)与最长公共子序列(LCS)的区别:
最长公共子串要求在原字符串中是连续的,而子序列只需要保持相对顺序一致,并不要求连续。
分析
根据standFord《算法导论》课程的方法一共有3种办法
- 暴力穷举法,这个不用说了都知道。
- 动态递归,也就是利用递归思路,自上而下。从m ->0。
- 备忘表法,自下而上(自底向上)。从0 ->m。备忘表法会丢到一些内容
2/3无论哪一个都是利用同一个核心:状态转移方程。(从别人的文章中看到的,我也忘记是哪里带来的了。)
f
(
m
,
n
)
=
{
0
,
m
=
0
∣
∣
n
=
0
f
(
m
−
1
,
n
−
1
)
+
1
,
a
[
m
]
=
b
[
n
]
m
a
x
(
f
(
m
−
1
,
n
)
,
f
(
m
−
1
,
n
)
)
,
a
[
m
]
≠
b
[
n
]
f(m,n) = \begin{cases} 0,& m=0||n=0\\ f(m-1,n-1) +1, &a[m]=b[n]\\ max(f(m-1,n),f(m-1,n)),&a[m] \neq b[n] \end{cases}
f(m,n)=⎩⎪⎨⎪⎧0,f(m−1,n−1)+1,max(f(m−1,n),f(m−1,n)),m=0∣∣n=0a[m]=b[n]a[m]̸=b[n]
代码
#include <algorithm>
#include <iostream>
#include <cmath>
#include <vector>
#include <string>
#include <queue>
using namespace std;
#define MAX_X 1000
#define MAX_Y 1000
string Result[MAX_X][MAX_Y];//由于C++中字符串自动初始化为"",不能判断是否为空,所以需要另外一个表格来判断是否已经有值了
bool bResult[MAX_X][MAX_Y];//用来判断是否已经有值了。
string maxString(string A, string B)
{
int lenA = A.length();
int lenB = B.length();
if (lenA > lenB)
return A;
return B;
}
string maxCommonString(string A, string B)
{
int lenA = A.length();
int lenB = B.length();
if (0 == lenA || 0 == lenB)
{
return "";
}
if (1 == lenA)
{
string::size_type idx;
idx = B.find(A);
if (idx == string::npos)
{
Result[lenA - 1][lenB - 1] = "";
bResult[lenA - 1][lenB - 1] = true;
}
else
{
Result[lenA - 1][lenB - 1] = A;
bResult[lenA - 1][lenB - 1] = true;
}
return Result[lenA - 1][lenB - 1];
}
if (1 == lenB)
{
string::size_type idx;
idx = A.find(B);
if (idx == string::npos)
{
Result[lenA - 1][lenB - 1] = "";
bResult[lenA - 1][lenB - 1] = true;
}
else
{
Result[lenA - 1][lenB - 1] = B;
bResult[lenA - 1][lenB - 1] = true;
}
return Result[lenA - 1][lenB - 1];
}
//进入递归。
if (A[lenA - 1] == B[lenB - 1])
{
if (false == bResult[lenA - 2][lenB - 2])
{
Result[lenA - 2][lenB - 2] = maxCommonString(A.substr(0, lenA - 1), B.substr(0, lenB - 1));
bResult[lenA - 2][lenB - 2] = true;
}
Result[lenA - 1][lenB - 1] = Result[lenA - 2][lenB - 2] + A[lenA - 1];
bResult[lenA - 1][lenB - 1] = true;
}
else
{
if (false == bResult[lenA - 2][lenB - 1])
{
Result[lenA - 2][lenB - 1] = maxCommonString(A.substr(0, lenA - 1), B);
bResult[lenA - 2][lenB - 1] = true;
}
if (false == bResult[lenA - 1][lenB - 2])
{
Result[lenA - 1][lenB - 2] = maxCommonString(A, B.substr(0, lenB - 1));
bResult[lenA - 1][lenB - 2] = true;
}
Result[lenA - 1][lenB - 1] = maxString(Result[lenA - 1][lenB - 2], Result[lenA - 2][lenB - 1]);
bResult[lenA - 1][lenB - 1] = true;
}
return Result[lenA - 1][lenB - 1];
}
int main()
{
string t1, t2;
cin >> t1;
cin >> t2;
cout << maxCommonString(t1, t2) << endl;
return 0;
}
参考资料
https://www.cnblogs.com/fengziwei/p/7827959.html
http://www.cnblogs.com/wangkundentisy/p/9346376.html