1. 程式人生 > >sincerit LCS最長公共子序列

sincerit LCS最長公共子序列

#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; }