《算法导论》-最大公共子串(连续) C语言版

1、最大公共子串与最大公共子序列

最大公共子串是指两个序列连续的最大公共子序列,例如 "efghi"和"eghib"的最大公共子串就是“ghi"


采用DP的思想,如果str1[i] = str2[j],那么此处的包含str1[i] 和 str2[j]公共子串的长度必然是包含str1[i-1]和str2[j-1]的公共子串的长度加1,那么现在我们可以重新定义lcs(i,j),即是lcs(i,j) = lcs(i-1,j-1) + 1,反之,lcs(i,j) = 0。

2.算法的改进
由于每一行的数据的生成只需要通过两个母串的对比,以及借助上一行的结果得到,因此除了当前行的上一行,之前行的数据均可以被抛弃。因此,该算法只需要用于保存上一行的计算结果的长为LEN的辅助数组空间。改进后的算法空间复杂度为O(min(m,n))
3、代码实现(C语言版)


#include 
#include 
#include 

/**************************************************************
函数:void Find_conLCS( char *str1, char *str2)
		str1:	待比较字符串1
		str2:	待比较字符串2
返回值:无
打印值:输出最大公共序列长度以及最大公共序列
时间复杂度:O(mn)
空间复杂度:O(mn)
***************************************************************/
void Find_conLCS( char *str1, char *str2)
{
	int i,j;
	int len = 0, end = -1, start = 0;
	int len1 = strlen(str1),
		len2 = strlen(str2);

	int **c = (int **)malloc(sizeof(int *) * (len1 + 1));
	for( i = 0; i <= len1; i++ )
		c[i] = (int *)malloc(sizeof(int) * (len2 + 1));
	
	for( i = 0; i <= len1; i++ )	//这里必须要把动态申请的二位数组清零,否则会有bug
		for( j = 0; j <= len2; j++ )
			c[i][j] = 0;

	for( i = 1; i <= len1; i++ )
		for( j = 1; j <= len2; j++ )
		{
			if( str1[i-1] == str2[j-1])
				c[i][j] = c[i-1][j-1] + 1;
			if( c[i][j] > len)
			{
				len = c[i][j];
				end = j;
			}
		}
	start = end - len + 1;
	printf("The number of Longest of continuous subsequence is : %d\n", len);
	printf("The longest of continuous subsequence is :");
	for( j = start; j <= end; j++)
		printf("%c ", str2[j-1]);
	printf("\n");

	for( i = 0; i <= len1; i++ )
		free(c[i]);
	free(c);
}

/**************************************************************
函数:void Find_conLCS1( char *longstr, char *shortstr)
		str1:	待比较字符串1
		str2:	待比较字符串2
返回值:无
打印值:输出最大公共序列长度以及最大公共序列
时间复杂度:O(mn)
空间复杂度:O(len(shortstr))
***************************************************************/
void Find_conLCS1( char *longstr, char *shortstr)
{
	int i, j;
	int len1 = strlen(longstr),
		len2 = strlen(shortstr);
	int len = 0, end = -1, start;

	int *c = (int *)malloc(sizeof(int) * (len2 + 1));
	
	for( i = 0; i <= len2; i++ )
		c[i] = 0;
	
	for( i = 0; i <= len1; i++)
		for( j = len2-1; j >= 0; j--)
		{
			if( longstr[i] == shortstr[j])
			{
				if( i == 0 || j == 0 )
					c[j] = 1;
				else c[j] = c[j-1] +1;
			}
			else c[j] = 0;
		
			if( c[j] > len)
			{
				len = c[j];
				end = j;
			}
		}

	start = end - len + 1;
	printf("The number of Longest of continuous subsequence is : %d\n", len);
	printf("The longest of continuous subsequence is :");
	for( i = start; i <= end; i++ )
		printf("%c ", shortstr[i]);
	printf("\n");

	free(c);
}

int main()
{
	char x[10] = "abcdefghi";
	char y[10] = "bdeghibjk";
	Find_conLCS1(x,y);
	system("pause");
}

你可能感兴趣的:(算法导论)