#include <iostream>
using namespace std;
void TestLongestCommenString();
/*
1 3 4 5 5 ,and 2 4 5 5 7 6
最长公共子序列是:4 5 5
动态规划问题
*/
/*
c[i][j] = c[i-1][j-1] + 1 (a[i] == b[j])
= max{c[i][j-1], c[i-1][j]} a[i] != b[j]
*/
/*
1.根据转移方程,递归求解
2.带记忆的递归求解
3.自底向上的动态规划求解
c[m,n] :长度
b[m,n] :记录公共字符
*/
const int LEN = 6;
// 动态规划解决问题
void LongestcommonString(const char *a, unsigned len1, const char *b, unsigned len2, int ** &lenMetrix, char ** &cMetrix);
// 从后往前算
void LongestcommonString_2(const char *a, unsigned len1, const char *b, unsigned len2, int lenMetrix[][LEN + 1], char cMetrix[][LEN + 1]);
// 从前往后
void LongestcommonString_3(const char *a, unsigned len1, const char *b, unsigned len2, int lenMetrix[][LEN + 1], char cMetrix[][LEN + 1]);
void PrintMetrix(int lenMetrix[][LEN + 1], char cMetrix[][LEN + 1]);
void PrintLongestCommonString(int lenMetrix[][LEN + 1], char cMetrix[][LEN + 1], char *a, int len);
// 优化1:用二维数组记录C
void LongestcommonString_4(const char *a, unsigned len1, const char *b, unsigned len2, int lenMetrix[][LEN + 1], char cMetrix[][LEN + 1]);
#include <string>
#include "11_LongestCommenString.h"
void TestLongestCommenString()
{
char *str1 = "ABCBDA";
char *str2 = "BDCABA";
int len1 = strlen(str1);
int len2 = strlen(str2);
int lenMetrix [LEN + 1][LEN + 1];
char cMetrix[LEN + 1][LEN + 1];
//LongestcommonString_2(str1, len1, str2, len2, lenMetrix, cMetrix);
LongestcommonString_2(str1, len1, str2, len2, lenMetrix, cMetrix);
PrintMetrix(lenMetrix, cMetrix);
PrintLongestCommonString(lenMetrix, cMetrix, str1, len1);
}
void LongestcommonString(const char *a, unsigned len1, const char *b, unsigned len2, int ** &lenMetrix, char ** &cMetrix)
{
for (unsigned i = 0; i < len1; ++i)
{
lenMetrix[i][0] = 0;
}
for (unsigned i = 0; i < len2; ++i)
{
lenMetrix[0][i] = 0;
}
for (unsigned i = 0; i < len1; ++i)
{
for (unsigned j = 0; j < len2; ++j)
{
if (a[i] == b[j])
{
if (i >= 1 && j >= 1)
{
lenMetrix[i][j] = lenMetrix[i - 1][j - 1] + 1;
cMetrix[i][j] = '1';
}
else
{
lenMetrix[i][j] = 1;
cMetrix[i][j] = '1';
}
}
else
{
if (i >= 1 && j >= 1)
{
int first = lenMetrix[i][j - 1];
int second = lenMetrix[i - 1][j];
if (first > second)
{
lenMetrix[i][j] = lenMetrix[i][j - 1];
cMetrix[i][j] = '2'; // 上面长,下面短
}
else
{
lenMetrix[i][j] = lenMetrix[i - 1][j];
cMetrix[i][j] = '3'; // 下面长,上面短
}
}
else // 0 1 / 1 0 / 0 0
{
if (i > j) // 1 0
{
lenMetrix[i][j] = lenMetrix[i - 1][j];
cMetrix[i][j] = '3';
}
else if (j > i)
{
lenMetrix[i][j] = lenMetrix[i][j - 1];
cMetrix[i][j] = '2';
}
else // 0 0
{
lenMetrix[i][j] = 0;
cMetrix[i][j] = '4';
}
}
}
}
}
}
// 从后往前算
void LongestcommonString_2(const char *a, unsigned len1, const char *b, unsigned len2, int lenMetrix[][LEN + 1], char cMetrix[][LEN + 1])
{
for (unsigned i = 0; i <= len1; ++i)
{
lenMetrix[i][0] = 0;
lenMetrix[i][len2] = 0;
cMetrix[i][len2] = '0';
}
for (unsigned i = 0; i <= len2; ++i)
{
lenMetrix[0][i] = 0;
lenMetrix[len1][i] = 0;
cMetrix[len1][i] = '0';
}
for (int i = len1 - 1; i >= 0; --i)
{
for (int j = len2 - 1; j >= 0; --j)
{
if (a[i] == b[j])
{
lenMetrix[i][j] = lenMetrix[i + 1][j + 1] + 1;
cMetrix[i][j] = '1';
}
else if (lenMetrix[i + 1][j] > lenMetrix[i][j + 1])
{
lenMetrix[i][j] = lenMetrix[i + 1][j];
cMetrix[i][j] = '2';
}
else
{
lenMetrix[i][j] = lenMetrix[i][j + 1];
cMetrix[i][j] = '3';
}
}
}
}
// 从前往后
// 第一行都不用
void LongestcommonString_3(const char *a, unsigned len1, const char *b, unsigned len2, int lenMetrix[][LEN + 1], char cMetrix[][LEN + 1])
{
for (unsigned i = 0; i <= len1; ++i)
{
lenMetrix[i][0] = 0;
}
for (unsigned i = 0; i <= len2; ++i)
{
lenMetrix[0][i] = 0;
}
for (int i = 1; i <= len1; ++i)
{
for (int j = 1; j <= len2; ++j)
{
if (a[i - 1] == b[j - 1])
{
lenMetrix[i][j] = lenMetrix[i - 1][j - 1] + 1;
cMetrix[i][j] = '1';
}
else if (lenMetrix[i - 1][j] > lenMetrix[i][j - 1])
{
lenMetrix[i][j] = lenMetrix[i - 1][j];
cMetrix[i][j] = '2';
}
else
{
lenMetrix[i][j] = lenMetrix[i][j - 1];
cMetrix[i][j] = '3';
}
}
}
}
void PrintMetrix(int lenMetrix[][LEN + 1], char cMetrix[][LEN + 1])
{
for (int i = 0; i <= LEN; ++i)
{
for (int j = 0; j <= LEN; ++j)
{
cout << lenMetrix[i][j] << ' ';
}
cout << endl;
}
cout << "----------------------------------" << endl;
for (int i = 0; i <= LEN; ++i)
{
for (int j = 0; j <= LEN; ++j)
{
cout << cMetrix[i][j] << ' ';
}
cout << endl;
}
}
void PrintLongestCommonString(int lenMetrix[][LEN + 1], char cMetrix[][LEN + 1], char *a, int len)
{
int i = 0;
int j = 0;
while (i <= LEN && j <= LEN && cMetrix[i][j])
{
switch(cMetrix[i][j])
{
case '1':
cout << a[i] << " ";
i++;
j++;
break;
case '2':
i++;
break;
case '3':
j++;
break;
}
}
}
/*
优化:
只需要c[i-1] c[i]
*/
void LongestcommonString_4(const char *a, unsigned len1, const char *b, unsigned len2, int lenMetrix[][LEN + 1], char cMetrix[][LEN + 1])
{
// 初始化
for (int i = 0; i <= len1; ++i)
{
lenMetrix[0][i] = 0;
}
for (int i = 1; i <= len1; ++i)
{
for (int j = 1; j <= len2; ++j)
{
if (a[i - 1] == b[j - 1])
{
lenMetrix[1][j] = lenMetrix[0][j - 1] + 1;
}
// lenMetrix[0][j]:存储的是[i-1][j]
// lenMetrix[1][j-1]:存储的是[i][j-1]
else if (lenMetrix[0][j] > lenMetrix[1][j - 1])
{
lenMetrix[1][j] = lenMetrix[0][j];
cMetrix[i][j] = '2';
}
else
{
lenMetrix[1][j] = lenMetrix[1][j - 1];
cMetrix[i][j] = '3';
}
}
}
}