最长公共子序列和最长公共子串(C语言实现)

14 篇文章 3 订阅

核心思想:
利用动态规划的思想,通过设置一个临时数组t[][],其中t[i][j]表示,以Str1[i]作为末尾和以Str[2]作为末尾的最长公共子序列或者子串的长度。

算法步骤:
(1)将输入的两个字符串分别存在数组a[]和b[]中,同时设置两个临时数组t1[][]和t2[][],第一个t1[i][j]表示a[]数组前i-1个字符串和b[]数组前j-1个字符串的最大公共子序列;第二个t2[i][j]表示a[]数组前i-1个字符串和b[]数组前j-1个字符串的最大公共子串;
(2)循坏遍历两个字符串的所有字符,当遍历到第一个字符串的第i个字符,第二个字符串的第j个字符时:
对于最长公共子序列:
若a[i]=b[j],则t1[i][j]=t1[i-1][j-1]+1;
若a[i]!=b[j],则t1[i][j]=Max{a[k][j],a[i][m]}
对于最长公共子串:
若a[i]=b[j],则t2[i][j]=t2[i-1][j-1]+1;
若a[i]!=b[j],则t2[i][j]=0。
(3)t1[][]数组最右下角的便是最长公共子序列的长度;而t2[][]数组中最大的元素才是最长公共子串的长度。

注意:
子序列:从字符串中顺序地取出字符组成的字符串;
子串:从字符串中连续地取出字符组成的字符串。

实例以及代码

//定义全局变量
int t1[20][20]={0},t2[20][20]={0};
char a[20],l1=1,b[20],l2=1;
//存储输入,初始化临时二维数组
void Input(){
	char ch;
	printf("请输入两个字符串:");
	ch=getchar();
	while(ch!=' ')
	{
		a[l1++]=ch;
		ch=getchar();
	}
	ch=getchar();
	while(ch!='\n')
	{
		b[l2++]=ch;
		ch=getchar();
	}
}
//对于a[i]是否等于b[j]的处理
void LCDSubsequence(){  //最长公共子序列
	int i,j,max,k;
	for(i=1;i<l1;i++)
		for(j=1;j<l2;j++)
		{
			if(a[i]==b[j])
				t1[i][j]=t1[i-1][j-1]+1;
			else
			{
				if(t[i-1][j]>t[i][j-1])
				  t[i][j]=t[i-1][j];
	  	  	  else
	  	  	      t[i][j]=t[i][j-1];
			}
		}
}
//对于a[i]是否等于b[j]的处理
void LCCSubsequence(){   //最长公共子串
	int i,j;
	for(i=1;i<l1;i++)
		for(j=1;j<l2;j++)
		{
			if(a[i]==b[j])
				t2[i][j]=t2[i-1][j-1]+1;
			else
			{
				t2[i][j]=0;
			}
		}
}

//分别输出
void Output(){
	printf("最长公共子序列为:");
	printf("%d\n",t1[l1-1][l2-1]);
	int i,j,max=0;
	printf("最长公共连续序列为:");
    for(i=1;i<l1;i++)
		for(j=1;j<l2;j++)
			if(t2[i][j]>max)
				max=t2[i][j];
	printf("%d",max);
}
int main(){
	Input();
	LCDSubsequence();
	LCCSubsequence();
	Output();
	return 0;
}

运行结果:
在这里插入图片描述

  • 8
    点赞
  • 1
    评论
  • 12
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 创作都市 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值