最长公共子序列问题

本文深入探讨了最长公共子序列的概念、算法设计及其实际应用,通过动态规划方法解决此类问题,并提供了实例代码。重点阐述了如何利用此算法在不同场景下找到序列之间的最大共享部分。

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

转自:

http://blog.youkuaiyun.com/jiahui524/article/details/6653181

问题描述:

最长公共子序列也称作最长公共子串(不要求连续),英文缩写为LCS(Longest Common Subsequence)。其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列。

 

例如:X(A,B,C,B,D,A,B)

        Y(B,D,C,A,B,A)

 

那么最长公共子序列就是:B,C,B,A

算法设计:用动态规划方法解决

最长公共子序列的结构:

设X = { x1 , ... , xm },Y = { y1 , ... , yn }及它们的最长子序列Z = { z1 , ... , zk }则:

1、若 xm = yn , 则 zk = xm = yn,且Z[k-1] 是 X[m-1] 和 Y[n-1] 的最长公共子序列

2、若 xm != yn ,且 zk != xm , 则 Z 是 X[m-1] 和 Y 的最长公共子序列

3、若 xm != yn , 且 zk != yn , 则 Z 是 Y[n-1] 和 X 的最长公共子序列

子问题的递归结构:

当 i = 0 , j = 0 时 , c[i][j] = 0

当 i , j > 0 ; xi = yi 时 , c[i][j] = c[i-1][j-1] + 1

当 i , j > 0 ; xi != yi 时 , c[i][j] = max { c[i][j-1] , c[i-1][j] }

 

还是以:X(A,B,C,B,D,A,B)

          Y(B,D,C,A,B,A)  为例

看下面的图:

 

 

由上面的分析:我们得到的源代码:

 

  1. //最长公共子序列代码模板  
  2.   
  3. #include <iostream>  
  4.   
  5. using namespace std;  
  6.   
  7.    
  8.   
  9. #define N 105  
  10.   
  11. int dp[N+1][N+1];  
  12.   
  13. char str1[N],str2[N];  
  14.   
  15.    
  16.   
  17. //比较两个数的大小  
  18.   
  19. int maxx(int a,int b){  
  20.   
  21.       if(a>b){  
  22.   
  23.            return a;  
  24.   
  25.       }  
  26.   
  27.       return b;  
  28.   
  29. }  
  30.   
  31.    
  32.   
  33. //函数功能:获取两个字符串的最长公共子序列的数目  
  34.   
  35. //len1:字符串1的长度  
  36.   
  37. //len2:字符串2的长度  
  38.   
  39. int LCSL(int len1,int len2){  
  40.   
  41.    
  42.   
  43.       int i,j;  
  44.   
  45.       int len=maxx(len1,len2);  
  46.   
  47.    
  48.   
  49.       for(i=0;i<=len;i++){  
  50.   
  51.            dp[i][0]=0;//y为空字符串  
  52.   
  53.            dp[0][i]=0;//x为空字符串  
  54.   
  55.       }  
  56.   
  57.    
  58.   
  59.       for(i=1;i<=len1;i++){  
  60.   
  61.            for(j=1;j<=len2;j++){  
  62.   
  63.                  if(str1[i-1]==str2[j-1]){  
  64.   
  65.                       dp[i][j]=dp[i-1][j-1]+1;  
  66.   
  67.                  }  
  68.   
  69.                  else{  
  70.   
  71.                       dp[i][j] = maxx(dp[i - 1][ j ] , dp[i][j - 1]) ;   
  72.   
  73.                  }  
  74.   
  75.            }  
  76.   
  77.    
  78.   
  79.       }  
  80.   
  81.       return dp[len1][len2];  
  82.   
  83. }  
  84.   
  85.    
  86.   
  87. int main(){  
  88.   
  89.    
  90.   
  91.       while(cin>>str1>>str2){  
  92.   
  93.    
  94.   
  95.            int len1=strlen(str1);//获取字符串1的长度  
  96.   
  97.            int len2=strlen(str2);//获取字符串2的长度  
  98.   
  99.    
  100.   
  101.            cout<<LCSL(len1,len2)<<endl;  
  102.   
  103.    
  104.   
  105.       }  
  106.   
  107.       return 0;  
  108.   
  109.    
  110.   
  111. }  


 

利用此模板能直接解决的题目:HDOJ1159 :http://acm.hdu.edu.cn/showproblem.php?pid=1159

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值