码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 1159 Common Subsequence(dp 最长公共子序列问题LCS)

时间:2016-04-06 23:14:35      阅读:215      评论:0      收藏:0      [点我收藏+]

标签:


 

最长公共子序列问题(LCS,Longerst Common Subsequence)

s1s2……si+1和t1t2……tj+1的公共子序列可能是:

  ①当si+1=tj+1时,在s1s2……si+1和t1t2……tj+1的公共子序列末尾追加一个。

  ②s1s2……si+1和t1t2……tj的公共子序列

  ③s1s2……si和t1t2……tj+1的公共子序列

所以易得到递推关系dp[i+1][j+1]=   max{ dp[i][j]+1 , dp[i][j+1] , dp[i+1][j]) }   (当si+1=tj+1时)

                  max{ dp[i][j+1] , dp[i+1][j]) }     (其他)

最后得到的dp[n][m]就是LCS的长度。

同时稍微思考一下,就可以发现当si+1=tj+1时,dp[i+1][j+1]只要等于dp[i][j]+1就可以了。


tips:

 

 

 

   怎么 思考呢 ,首先因为si+1=tj+1,显然si和tj+1,si+1和 tj均不相等。那么 dp[i][j+1] 和 dp[i+1][j] 其实也就等于dp[i][j]。


 ①要注意的是s1第i个字母在数组中的位置是s1[i-1]而不是s[i],s2同理。所以下面这个判断的是s1[i-1]==s2[j-1]  它想表达的就是s1的第i个字母与s2的第j个字母是否相等,所以与上面的递推式是一致的 

1 if(  s1[i-1] == s2[j-1] )
2     dp[i][j] = dp[i-1][j-1]+1;
3 else
4     dp[i][j] = max( dp[i-1][j] , dp[i][j-1] );

其实啊 我想了想 觉得这个数组从0开始用和从1开始用 还是很有讲究的。

AC代码如下:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 int dp[5000][5000];
 7 char s1[5000],s2[5000];
 8 int main()
 9 {
10 
11     while(~scanf("%s%s",&s1,&s2))
12     {
13         int len1=strlen(s1);
14         int len2=strlen(s2);
15         for(int i=0 ; i <= len1 ; i++)
16             dp[i][0]=0;
17         for(int j=0 ; j <= len2 ; j++)
18             dp[0][j]=0;
19 
20         for(int i=1 ; i <= len1 ; i++)
21             for(int j=1 ; j <= len2 ; j++)
22         {
23             if(  s1[i-1] == s2[j-1] )
24                 dp[i][j] = dp[i-1][j-1]+1;
25             else
26                 dp[i][j] = max( dp[i-1][j] , dp[i][j-1] );
27         }
28         printf("%d\n", dp[len1][len2] );
29     }
30     return 0;
31 }

 

hdu 1159 Common Subsequence(dp 最长公共子序列问题LCS)

标签:

原文地址:http://www.cnblogs.com/luosuo10/p/5346451.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!