求解两个字符串的最长公共子串

一、前言

求解两个字符串的最长公共子串(Longest Common Substring, LCS)与求解两个字符串的最长公共子序列(Longest Common Subsequence, LCS)是不一样的,求解最长公共子序列问题请参阅我的另一篇博客

http://blog.csdn.net/heart_love/article/details/50804301

假定给出两个字符串X=“abcdef"和Y=“abacdef"那么"a"、"ab"、"cdef"等都是其公共子串,其中"cdef"是X和Y的最长公共子串。

二、求解算法

对于两个字符串X={x1,x2,....xm}和Y={y1,y2,.....yn},我们利用一个二维数组c[i][j]来记录Xi与Yj是否相等,如果Xi == Yj,那么c[i][j] = 1,否则c[i][j] = 0。如下图所示:


然后我们遍历所有的斜下角,找出最多的连续为1的值。这种遍历太浪费时间,我们把算法改进一下:如果Xi == Yj,那么c[i][j] = c[i - 1][j - 1] + 1,否则c[i][j] = 0。如下图所示:


然后我们找出二维数组中的最大值,即可求出其最长公共子串。此算法还有一个缺点就是所使用的二维数组占用了过的内存,我们继续对算法进行改进,使用一维数组来保存值:具体算法如下面的代码所示

#include <iostream>

using namespace std;

char *lcs(const char X[],const char Y[],char str[]);
int main()
{
	char str[1024];
	lcs("aecdfab", "abecdfa", str);
	cout << str << endl;
}

char *lcs(const char X[], const char Y[], char str[])
{
	int Xlen = strlen(X);
	int Ylen = strlen(Y);

	int *pre = (int *)malloc(sizeof(int)* Ylen);//用来记录前一行的数据
	int *cur = (int *)malloc(sizeof(int)* Ylen);//用来记录当前行的数据
	int max[2] = { 0 };							//max[0]用来记录最长公共子串的长度,max[1]用来记录此时X串的下表

	int i, j;
	/*初始化pre数组*/
	for (j = 0; j < Ylen; j++)
	{
		if (X[0] == Y[j])
		{
			pre[j] = 1;
			max[0] = pre[j] > max[0] ? pre[j]:max[0];
		}
		else
			pre[j] = 0;
	}

	for (i = 1; i < Xlen; i++)
	{
		for (j = 0; j < Ylen;j++)
		{
			if (j == 0)
			{
				if (X[i] == Y[0])
				{
					cur[0] = 1;
					max[0] = cur[0] > max[0] ? cur[0] : max[0];
					max[1] = cur[0] > max[0] ? i : max[1];
				}else
					cur[0] = 0;
			}else	
			{
				if (X[i] == Y[j])
				{
					cur[j] = pre[j - 1] + 1;
					max[1] = cur[j] > max[0] ? i : max[1];
					max[0] = cur[j] > max[0] ? cur[j] : max[0];
				}
				else
					cur[j] = 0;
				pre[j - 1] = cur[j - 1];
			}
		}
		pre[j] = cur[j];
	}

	strncpy(str, X + max[1] - max[0] + 1, max[0]);
	str[max[0]] = '\0';
	free(pre);
	free(cur);
	return str;
}
运行结果为:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值