会慢慢写最长公共子序列、最短编辑距离等与字符串相关的算法,其实也就是数组相关的算法...
一、最长公共子序列
Solve1里递推公式为:
dp[i][j] = 0 if i = 0 or j = 0
dp[i][j] = dp[i-1][j-1]+1 if s1[i-1] = s2[j-1]
dp[i][j] = max{dp[i-1][j],dp[i][j-1]} if s1[i-1] != s2[j-1]
这里i、j并不是s1、s2中字符下标而是已经s1前i个字符与s2前j个字符,dp[i][j]表示s1前i个字符与s2前j个字符最长公共子序列
Solve1只打印了最长公共子序列的其中一个,没有考虑多个相同的最长公共子序列
Solve2稍微变换了递推公式:
dp[i][j]表示s1前i+1个字符与s2前j+1个字符的最长公共子序列,没什么太大变换
Solve3只用了一维数组,减少了空间复杂度
Solve4是递归写法
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#define _DEBUG
int max(int a, int b){
return a>b?a:b;
}
void Solve1(char s1[], char s2[]){
int i,j;//i、j表示扫过的s1、s2长度
int len1 = strlen(s1);
int len2 = strlen(s2);
int dp[len1+1][len2+1];
for(i = 0; i <= len1; ++i) dp[i][0] = 0;
for(j = 0; j <= len2; ++j) dp[0][j] = 0;
for(i = 1; i <= len1; ++i){
for(j = 1; j <= len2; ++j){
if(s1[i-1] == s2[j-1]){//是i-1 与 j-1
dp[i][j] = dp[i-1][j-1] + 1;
}else{
dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
}
}
}
#ifdef _DEBUG
for(i = 0; i <= len1; ++i){
for(j = 0; j<= len2; ++j){
printf("%d ",dp[i][j]);
}
printf("\n");
}
#endif// _DEBUG
printf("Solve1:%d\n",dp[len1][len2]);
for(i = len1; i >= 0; ){
for(j = len2; j >= 0; ){
if(s1[i-1] == s2[j-1]){
printf("%c ",s1[i-1]);
--i;
--j;
}else{
if(dp[i][j-1] > dp[i-1][j]){
--j;
}else{
--i;
}
}
}
}
printf("\n");
}
/*错误
//dp[][0]与dp[0][]错误
void Solve2(char