尝试另辟蹊径,但是时间复杂度爆炸。
#include <algorithm>
#include <cstdio>
#include <stack>
#include <vector>
#include <tuple>
constexpr int MAX_N = 1001;
constexpr int MAX_M = 1001;
// 方法0:动态规划
// 原理:len_shared的来源是斜向、横向、竖向。
// 因为“len_shared[i-1][j]或len_shared[i][j-1] >= len_shared[i-1][j-1]”,
// 并且“len_shared[i-1][j-1]+1 > len_shared[i-1][j-1]”,
// 所以“len_shared[i-1][j-1]+1 >= len_shared[i-1][j]或len_shared[i][j-1]”,
// 所以在“s_a[i] == s_b[j]”为true时,不用考虑len_shared[i-1][j]或len_shared[i][j-1],
// 在“s_a[i] == s_b[j]”为false时,不用考虑len_shared[i-1][j-1]。
// 优点:容易计算复杂度
// 缺点:不太方便记录路径
// 方法1:图遍历
// 原理:记录下斜向行走的次数,到终止节点时取max
// 优点:直观(前提是刚好这么想了),方便记录路径
// 缺点:时间复杂度难算,并且很高,需要精简探索路径
/*方法0*/
int method0(int N, int M, char s_a[], char s_b[])
{
int count = 0;
std::vector<std::vector<int>> len_shared(N+1, std::vector<int>(M+1, 0));
for (int i = 0; i < N; ++i) {
for (int j = 0; j < M; ++j) {
++count;
if (s_a[i] == s_b[j]) {
len_shared[i + 1][j + 1] = len_shared[i][j] + 1;
} else {
len_shared[i + 1][j + 1] = std::max(len_shared[i + 1][j],
len_shared[i][j + 1]);
}
}
}
//printf("method0 loop count = %d\n", count);
return len_shared[N][M];
}
/*方法1*/
int method1(int N, int M, char s_a[], char s_b[])
{
int count = 0;
// i, j, length
std::stack<std::tuple<int,int,int>> tobevisited;
int i, j, len_shared;
int max_len_shared = 0;
tobevisited.emplace(0,0,0);
while(!tobevisited.empty()){
++count;
const auto &now = tobevisited.top();
i = std::get<0>(now);
j = std::get<1>(now);
len_shared = std::get<2>(now);
if(i == N || j == M){
tobevisited.pop();
if(max_len_shared < len_shared){
max_len_shared = len_shared;
}
}else{
if(s_a[i] == s_b[j]){
//剪枝,此时没有必要横向、纵向探索
tobevisited.pop();
tobevisited.emplace(i+1,j+1,len_shared+1);
}
else{
//剪枝,此时没有必要斜向探索
tobevisited.pop();
tobevisited.emplace(i+1,j,len_shared);
tobevisited.emplace(i,j+1,len_shared);
}
}
}
//printf("method1 loop count = %d\n", count);
return max_len_shared;
}
int main()
{
char s_a[MAX_N] = { 0 };
char s_b[MAX_M] = { 0 };
int N, M;
scanf("%d%d", &N, &M);
scanf("%s", s_a);
scanf("%s", s_b);
printf("%d\n", method0(N, M, s_a, s_b));
//printf("%d\n", method1(N, M, s_a, s_b));
return 0;
}
把注释去掉,输入
10 20
chktypadik
wmmmjtrjrromziefyftg
输出
method0 loop count = 200
2
method1 loop count = 35415170
2