最长公共子字符串

本文介绍了一种使用动态规划寻找两个字符串中最长公共子串的方法,并通过一个具体示例展示了如何构建并利用二维矩阵(实际在一维数组中实现)来找到最长公共子串及其长度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

找两个字符串的最长公共子串,这个子串要求在原字符串中是连续的。其实这又是一个序贯决策问题,可以用动态规划来求解。我们采用一个二维矩阵来记录中间的结果。这个二维矩阵怎么构造呢?直接举个例子吧:"bab"和"caba"(当然我们现在一眼就可以看出来最长公共子串是"ba"或"ab")

   b  a  b

c  0  0  0

a  0  1  0

b  1  0  1

a  0  1  0

我们看矩阵的斜对角线最长的那个就能找出最长公共子串。

不过在二维矩阵上找最长的由1组成的斜对角线也是件麻烦费时的事,下面改进:当要在矩阵是填1时让它等于其左上角元素加1。

   b  a  b

c  0  0  0

a  0  1  0

b  1  0  2

a  0  2  0

这样矩阵中的最大元素就是 最长公共子串的长度。

在构造这个二维矩阵的过程中由于得出矩阵的某一行后其上一行就没用了,所以实际上在程序中可以用一维数组来代替这个矩阵

#include <stdio.h>
#include <string.h>

void find_common_str(char *a, char *b)
{
	if(a==NULL || b==NULL)
		return;
	int xlen = strlen(a);//矩阵横行的长度
	int ylen = strlen(b);//矩阵纵行的长度
	int *temp = new int[xlen];//保存上一行的最大公共字符串长度
	int *curr = new int[xlen];//保存当前行的最大公共字符串长度
	int max = 0;//最大公共字符串长度初始化为0
	int pos_max;//最大公共字符串的最后一个字符位置
	memset(temp,0,xlen);//清0
	int i,j;
	for(i=0;i<ylen;i++)
	{
		memset(curr,0,xlen);//清0
		for(j=0;j<xlen;j++)
		{
			if(b[i] == a[j])//如果相等,则可以在curr[]中记录公共字符串长度
			{
				if(j==0)//如果在第一列,则将其设为1,因为其没有上一行对角线上的值
				{
					curr[j]=1;
				}
				else//如果不在第一列
				{
					curr[j]=temp[j-1]+1;//curr[j]的值是上一行对角线上的值加1
				}
				if(curr[j] > max)//更新最大公共字符串的长度及其位置
				{
					max = curr[j];
					pos_max = j;
				}
			}
		}
		for(j=0;j<xlen;j++)//保存当前行的数值
			temp[j] = curr[j];
	}
	printf("最长公共子字符串长度为:%d\n",max);
	printf("最长公共子字符串为:");
	for(i=pos_max-max+1;i<=pos_max;i++)//pos_max记录的是横行坐标,所以打印字符串a的值,pos_max是公共字符串的最后一个字符的下标,第一个字符的下标是pos_max-count+1
		printf("%c",a[i]);
	printf("\n");
	delete [] temp;
	delete [] curr;
	temp = NULL;
	curr = NULL;
}

int main()
{
	char a[] = "21232523311324";
	char b[] = "312123223445";
	printf("字符串1为:%s\n",a);
	printf("字符串2为:%s\n",b);
	find_common_str(a,b);
	return 0;
}


参考:http://www.cnblogs.com/zhangchaoyang/articles/2012070.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值