动态规划算法求最长公共子序列问题
问题描述
【问题描述】
字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列。
给定两个字符序列A和B,如果字符序列Z既是A的子序列,又是B的子序列,则称序列Z是A和B的公共子序列。该问题是求两序列A和B的最长公共子序列(LCS)。
【问题分析】
dp[i][j]为子序列(a0,a1,…,ai-1)和(b0,b1,…,bj-1)的最长公共子序列的长度。
对应的状态转移方程如下:

C语言的实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| #include<stdio.h> #include<string.h>
char str1[100]; char str2[100];
int c[100][100]; int b[100][100];
void print_LCS(int lenght1, int lenght2){ if(lenght1 == 0 || lenght2 == 0){ return; } if(b[lenght1][lenght2] == 1){ print_LCS(lenght1-1,lenght2-1); printf("%c",str1[lenght1-1]); } else if(b[lenght1][lenght2] == 2){ print_LCS(lenght1-1,lenght2); }else{ print_LCS(lenght1,lenght2-1); } }
void LCS(char str1[], char str2[]){ int str1_lenght, str2_lenght; str1_lenght = strlen(str1); str2_lenght = strlen(str2); if(str1_lenght == 0 || str2_lenght == 0){ printf("%s\n", "No sub seqence"); return; } int i, j; for(i = 0; i <= str1_lenght; i++){ c[i][0] = 0; } for(j = 0; j <= str2_lenght; j++){ c[0][j] = 0; } for(i = 1; i <= str1_lenght; i++){ for(j = 1; j <= str2_lenght; j++){ if (str1[i-1] == str2[j-1]){ c[i][j] = c[i-1][j-1] + 1; b[i][j] = 1; } else if(c[i-1][j] > c[i][j-1]){ c[i][j] = c[i-1][j]; b[i][j] = 2; } else{ c[i][j] = c[i][j-1]; b[i][j] = 3; } } } if(c[str1_lenght][str2_lenght] <= 0){ printf("%s\n","No sub squence"); return; } printf("size = %d\n", c[str1_lenght][str2_lenght]); print_LCS(str1_lenght,str2_lenght); printf("\n"); }
int main(){ printf("请输入第一个字符串:"); scanf("%s", str1); printf("请输入第二个字符串:"); scanf("%s", str2); LCS(str1,str2); return 0; }
|
运行截图
