#include <stdio.h>
#include <cstring>
#define max(a,b)a>b?a:b
int dp[100][100]; // dp[i][j]表示str1到i结尾的子串与str2到j结尾的最大公共子串
// 转移方程 对于str1[i] == str2[j]时, dp[i][j] = dp[i-1][j-1] + 1
// 不同时 dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
// 初始值 dp[0][0~m] = dp[0~n][0] = 0; 也就是第0行和第0列都为0
int vis[100][100];
int LCS(char* str1, char* str2) {
memset(dp, 0, sizeof(dp));
int str1_len = strlen(str1);
int str2_len = strlen(str2);
for (int i = 1; i <= str1_len; i++) {
for (int j = 1; j <= str2_len; j++) {
if (str1[i-1] == str2[j-1]) {
dp[i][j] = dp[i-1][j-1] + 1;
vis[i][j] = 1;
} else {
// dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
if (dp[i-1][j] > dp[i][j-1]) {
dp[i][j] = dp[i-1][j];
vis[i][j] = 2;
} else {
dp[i][j] = dp[i][j-1];
vis[i][j] = 3;
}
}
}
}
return dp[str1_len][str2_len];
}
void getResult(int i, int j, char* r) {
if (i == 0 || j == 0) return;
if (vis[i][j] == 1) {
getResult(i-1, j-1, r); // 该位置找到了一个字符答案,因为dp[i][j] = dp[i-1][j-1]+1;
printf("%c", r[i-1]);
} else if (vis[i][j] == 2) {
getResult(i-1, j, r); // dp[i][j] = dp[i-1][j];
} else {
getResult(i, j-1, r); // dp[i][j] = dp[i][j-1];
}
}
void show(char* r, char* s) {
printf(" ");
for (int i = 0; i < strlen(s); i++) printf("%c ", s[i]);
printf("\n");
int k = 0;
for (int i = 0; i <= strlen(r); i++) {
if (i >= 1) printf("%c ", r[k++]);
else printf(" ");
for (int j = 0; j <= strlen(s); j++){
printf("%d ", dp[i][j]);
}
printf("\n");
}
printf("\n");
}
int main() {
char r[] = {"asdfghjkl"};
char s[] = {"dfgcvzasdf"};
printf("%s\n", r);
printf("%s\n", s);
int len = LCS(r, s);
printf("%d\n", len);
//show(r, s); 这里是个规律表
getResult(strlen(r), strlen(s), r);
return 0;
}
sincerit LCS最长公共子序列
猜你喜欢
转载自blog.csdn.net/sincerit/article/details/84555923
今日推荐
周排行