最长公共子串/子序列

最长公共子串:找两个字符串的最长公共子串,要求在原字符串中是连续的

最长公共子序列:不要求连续

最长公共子串思路:

声明一个二维数组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 }



 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值