最长公共子字符串(动态规划)

     X = <a, b, c, f, b, c>

     Y = <a, b, f, c, a, b>

     X和Y的Longest Common Substring为 <a, b>长度为2


     动态规划解法

    c[i][j]表示X0...Xi和Y0...Yj的最大SubstringXi=Yj)的长度,比如

   X = <y, e, d, f>

   Y = <y, e, k, f>

   c[1][1] = 1

   c[2][2] = 2

   c[3][3] = 0

   c[4][4] = 1

   动态转移方程为:

   如果xi == yj, 则 c[i][j] = c[i-1][j-1]+1

   如果xi ! = yj,  那么c[i][j] = 0

   最后求Longest Common Substring的长度等于

   max{  c[i][j],  1<=i<=n, 1<=j<=m}

 完整的代码如下:

  1. /**  
  2. 找出两个字符串的最长公共连续子串的长度 
  3. ** author :liuzhiwei   
  4. ** data   :2011-08-16 
  5. **/   
  6. #include "stdio.h"  
  7. #include "string.h"  
  8. #include "stdlib.h"  
  9.   
  10. int longest_common_substring(char *str1, char *str2)  
  11. {  
  12.     int i,j,k,len1,len2,max,x,y;  
  13.     len1 = strlen(str1);  
  14.     len2 = strlen(str2);  
  15.     int **c = new int*[len1+1];  
  16.     for(i = 0; i < len1+1; i++)  
  17.         c[i] = new int[len2+1];  
  18.     for(i = 0; i < len1+1; i++)  
  19.         c[i][0]=0;        //第0列都初始化为0  
  20.     for(j = 0; j < len2+1; j++)  
  21.         c[0][j]=0;        //第0行都初始化为0   
  22.     max = -1;  
  23.     for(i = 1 ; i < len1+1 ; i++)  
  24.     {  
  25.         for(j = 1; j < len2+1; j++)  
  26.         {  
  27.             if(str1[i]==str2[j])     //只需要跟左上方的c[i-1][j-1]比较就可以了  
  28.                 c[i][j]=c[i-1][j-1]+1;  
  29.             else                         
  30.                 c[i][j]=0;  
  31.             if(c[i][j]>max)  
  32.             {  
  33.                 max=c[i][j];  
  34.                 x=i;  
  35.                 y=j;  
  36.             }  
  37.         }  
  38.     }  
  39.   
  40.     //输出公共子串  
  41.     char s[1000];  
  42.     k=max;  
  43.     i=x-1,j=y-1;  
  44.     s[k--]='\0';  
  45.     while(i>=0 && j>=0)  
  46.     {  
  47.         if(str1[i]==str2[j])  
  48.         {  
  49.             s[k--]=str1[i];  
  50.             i--;  
  51.             j--;  
  52.         }  
  53.         else       //只要有一个不相等,就说明相等的公共字符断了,不连续了  
  54.             break;  
  55.     }  
  56.     printf("最长公共子串为:");  
  57.     puts(s);  
  58.     for(i = 0; i < len1+1; i++)         //释放动态申请的二维数组  
  59.         delete[] c[i];  
  60.     delete[] c;  
  61.     return max;  
  62. }  
  63. int main(void)  
  64. {  
  65.     char str1[1000],str2[1000];  
  66.     printf("请输入第一个字符串:");  
  67.     gets(str1);  
  68.     printf("请输入第二个字符串:");  
  69.     gets(str2);  
  70.     int len = longest_common_substring(str1, str2);  
  71.     printf("最长公共连续子串的长度为:%d\n",len);  
  72.     system("pause");  
  73.     return 0;  
  74. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值