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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 1159 Common Subsequence(dp 最长公共子序列问题LCS)相关的知识,希望对你有一定的参考价值。


 

最长公共子序列问题(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)的主要内容,如果未能解决你的问题,请参考以下文章

HDU 1159 Common Subsequence

HDU 1159 Common Subsequence(裸LCS)

hdu 1159 Common Subsequence(最长公共子序列)

hdu-1159 Common Subsequence

题解报告:hdu 1159 Common Subsequence

hdu 1159 Common Subsequence(lcs)