最长公共子串:找两个字符串的最长公共子串,要求在原字符串中是连续的
最长公共子序列:不要求连续
最长公共子串思路:
声明一个二维数组dp[][]来存放相对应的最长公共子串数
arr1[m]=arr2[n]时,dp[m+1][n+1]=1+dp[m][n] 即当子序列中第 m+1 元素与目标序列中第 n+1 元素相同时,子序列前 m+1 个元素与目标序列前 n+1 个元素的最长公共子串数为子序列前 m 个元素与目标序列前 n 个元素的最长公共子串数 + 1;
arr1[m] != arr2[n]时,dp[m+1][n+1]=0;即当子序列中第 m+1 元素与目标序列中第 n+1 元素不相同时,子序列前 m+1 个元素与目标序列前 n+1 个元素的最长公共子串长为0 ;第二步:找出最大值,依次输出其左上角
#include<stdio.h>
int weight[101];//子串权值
char substr[101];//子串字母
char sbustrs[100][100];//
int maxlcs=0;//LCS大小
int a=0;
char arr1[]="bab";
char arr2[]="caba";
int dp[101][101]={0};//dp[i][j]存放字串前i-1,目标串前j-1个元素的LCS,初始全为0
int LCS(char *arr1,int size1 ,char *arr2,int size2 )//求出dp[][];
{
for(int i=0 ;i < size1; i++ )//依次增加子序列长度
{
for(int j=0 ;j< size2; j++)//依次增加目标序列长度
{
if(arr1[i]==arr2[j])
{
dp[j+1][i+1]=dp[j][i]+1;//当前匹配相同,对应LCS等于前一LCS+1
if(maxlcs<dp[j+1][i+1])maxlcs= dp[j+1][i+1];//找到LCS的最大值
}
else dp[j+1][i+1]=0;//当前匹配不同,对应LCS等于左侧和上侧LCS中的较大值
}
}
return 0;
}
int Find ( int n ,int m ,int nextmax )//找出所有匹配点,记录相应字符和权值
{
int k, j;
if (nextmax==0){ printf("\n");return 0;}
for(k=m+n ; k>0 ;k--)
{
for( j=n ; j>0 && (k-j)<(m+1) ; j--)
{
if(dp[k-j][j]==nextmax)
{
printf("%d %d %d",k-j,j,nextmax);
printf("%c ",arr1[j-1]);
if (nextmax==0) printf("\n");
Find(j-1,k-j-1,nextmax-1);//递归查找下一层级
}
}
}
return 0;
}
int main()
{
LCS(arr1,3,arr2,4);
Find(3,4,maxlcs);
return 0;
}
最长公共子序列思路:
第一步:声明一个二维数组dp[][]来存放相对应的最长公共子序列数
arr1[m]=arr2[n]时,dp[m+1][n+1]=1+dp[m][n] 即当子序列中第 m+1 元素与目标序列中第 n+1 元素相同时,子序列前 m+1 个元素与目标序列前 n+1 个元素的最长公共子序列数为子序列前 m 个元素与目标序列前 n 个元素的最长公共子序列数 + 1;
arr1[m] != arr2[n]时,dp[m+1][n+1]=max{dp[m][n+1],dp[m+1][n]} 即当子序列中第 m+1 元素与目标序列中第 n+1 元素不相同时,子序列前 m+1 个元素与目标序列前 n+1 个元素的最长公共子序列数为子序列前 m 个元素与目标序列前 n+1 个元素的最长公共子序列数 和 子序列前 m+1 个元素与目标序列前 n 个元素的最长公共子序列数中的较大值 ;
第二步:递归找出每一个匹配点对应的子序列,递归输出
1 #include<stdio.h>
2 char substr[101];//子串字母
3 int maxlcs=0;//LCS大小
4 char arr1[]="DADFDAB";
5 char arr2[]="ABDEFAFCD";
6 int dp[101][101]={0};//dp[i][j]存放字串前i-1,目标串前j-1个元素的LCS,初始全为0
7 int LCS(char *arr1,int size1 ,char *arr2,int size2 )//求出dp[][];
8 {
9 for(int i=0 ;i < size1; i++ )//依次增加子序列长度
10 {
11 for(int j=0 ;j< size2; j++)//依次增加目标序列长度
12 {
13 if(arr1[i]==arr2[j]) dp[j+1][i+1]=dp[j][i]+1;//当前匹配相同,对应LCS等于前一LCS+1
14 else dp[j+1][i+1]=(dp[j+1][i]>dp[j][i+1]?dp[j+1][i]:dp[j][i+1]);//当前匹配不同,对应LCS等于左侧和上侧LCS中的较大值
15 }
16 }
17 maxlcs= dp[size2][size1];//找到LCS的最大值
18 return 0;
19 }
20 int Find ( int n ,int m ,int nextmax )//找出所有匹配点,记录相应字符和权值
21 {
22 int k, j;
23 if (nextmax==0){ printf("%s \n",substr);return 0;}//当找到首个元素后输出记录
24 for(k=m+n ; k>0 ;k--)
25 {
26 for( j=n ; j>0 && (k-j)<(m+1) ; j--)
27 {
28 if((dp[k-j][j]==nextmax) && (arr1[j-1]==arr2[k-j-1]))//权值为当前最大,且对应字母匹配则记录
29 {
30 substr[maxlcs-nextmax]=arr1[j-1];//将记录存入数组与递归层数相对应位置,新分支覆盖原有分支,保留共用部分
31 Find(j-1,k-j-1,nextmax-1);//递归查找下一层级
32 }
33 }
34 }
35 return 0;
36 }
37 int main()
38 {
39 LCS(arr1,7,arr2,9);
40 Find(7,9,maxlcs);
41 return 0;
42 }