首页 > 代码库 > 最长公共子串(LCS)

最长公共子串(LCS)

最长公共子串(LCS)

找两个字符串的最长公共子串,这个子串要求在原字符串中是连续的。其实这又是一个序贯决策问题,可以用动态规划来求解。我们采用一个二维矩阵来记录中间的结果。这个二维矩阵怎么构造呢?直接举个例子吧:"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

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

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

void GetMaxlenChildStr(char* str1,int n1,char* str2,int n2,char* res)
{
	int max=0;                        //矩阵元素中的最大值
	int *pre=new int[n2];     //保存矩阵的上一行
	int *cur=new int[n2];     //当前行
	for (int i=0;i<n2;i++)     //初始化
	{
		pre[i]=0;
	}
	for (int i=0;i<n2;i++)
	{
		cur[i]=0;
	}
   int pos=0;                      //矩阵元素最大值出现在第几列
   for (int i=0;i<n1;i++)
   {
	   for (int j=0;j<n2;j++)
	   {
              if (str1[i]==str2[j])
              {
				  if (j==0)
				  {
                     cur[j]=1;
				  } 
				  else
				  {
                      cur[j]=pre[j-1]+1;   
				  }
				  if (cur[j]>max)
				  {
					  max=cur[j];
					  pos=j;
				  }
              } 
	   }
     for (int i=0;i<n2;i++)
     {
         pre[i]=cur[i];
     }
   }
    strncpy(res,str2+pos-max+1,max);
}
int main()
{
        char str2[]="aba";
	char str1[]="cabda";
	char  res[5]={'\0'};
        GetMaxlenChildStr(str1,5,str2,3,res);
	return 0;
}
http://www.cnblogs.com/zhangchaoyang/articles/2012070.html#3022705

最长公共子串(LCS)