状态转移方程如下:
刚开始完全不理解当xi!=yj时,为什么Cij要等于
以s1作为标准,当前已经s1下标为i(即i不变,j在变化),匹配时s2的j是依次递增的,那么当s1i!=s2j时,那么此时Cij的值就是C[i,j-1]的值
以s2作为标准,当前已经s2下标为j(即j不变,i在变化),匹配时s1的i是依次递增的,那么当s1i!=s2j时,那么此时Cij的值就是C[i-1,j]的值
正因为Cij可视为以上两种不同标准的匹配,所以Cij就取其中最大那个值作为Cij
推荐博文:1点击打开链接 2点击打开链接 感谢两位dalao讲解!谢谢!
#include<stdio.h>
#include<string>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
char s1[100],s2[100];
int maxlen[100][100];//用来保存每个状态的最长公共子序列长度
int flag[100][100];//用来记录路径,方便输出最长公共子序列
void LCS()
{
int i,j,k,len1,len2;
len1=strlen(s1);
len2=strlen(s2);
for(i=0; i<=len1; i++)//当i=0或者j=0时,maxlen赋为0
maxlen[i][0]=0;
for(i=0; i<=len2; i++)
maxlen[0][i]=0;
memset(flag,0,sizeof(flag));
for(i=1; i<=len1; i++)
{
for(j=1; j<=len2; j++)
{
if(s1[i-1]==s2[j-1])//注意数组下标,amxlen矩阵起始位置为(1,1),而s1,s2数组起始位置为0
{
maxlen[i][j]=maxlen[i-1][j-1]+1;
flag[i][j]=1;//说明这个位置上s1[i]==s2[j],也可以说是这个值从斜上方而来
}
else
{
if(maxlen[i-1][j]>=maxlen[i][j-1])
{
maxlen[i][j]=maxlen[i-1][j];
flag[i][j]=2;//这个值从“上”方而来
}
}
else
{
maxlen[i][j]=maxlen[i][j-1];
flag[i][j]=3;//这个值从“左边”而来
}
}
}
}
/*for(i=1; i<=len1; i++)
{
for(j=1; j<=len2; j++)
{
printf("%d ",flag[i][j]);
}
printf("\n");
}
用来查看flag矩阵
*/
}
void getLCS()
{
int i,j,k,len1,len2;
i=strlen(s1);
j=strlen(s2);
char ans[100];
k=0;
while(i>0&&j>0)
{
if(flag[i][j]==1)
{
ans[k++]=s1[i-1];//注意数组下标,flag矩阵起始位置为(1,1),而s1,s2数组起始位置为0
i--;
j--;
}
else if(flag[i][j]==2)i--;
else j--;
//实际上就是在寻找flag为'1'的位置,并将那个位置上的s1(或者s2,因为当flag==1时,s1[i]==s2[j])存入结果数组中
}
for(j=k-1; j>=0; j--)//倒着输出lcs,因为我们是从尾向头开始找lcs子序列的
printf("%c",ans[j]);
printf("\n");
}
int main()
{
int len1,len2,i,j;
while(scanf("%s%s",s1,s2)!=EOF)
{
LCS();
printf("%d\n",maxlen[strlen(s1)][strlen(s2)]);
getLCS();
}
return 0;
}
/*
13456778
357486782
abcbdab
bdcaba
*/
”斜上方“即是当前s1i==s2j,maxlen{i,j}=maxlen[i-1,j-1]+1;
”左方“即是当前最大值来自左边,maxlen{i,j}=maxlen[i,j-1];
上方“即是当前最大值来自上方,maxlen{i,j}=maxlen[i-1,j];