HDU1159 Common Subsequence

题目描述:

  就是求最长公共字串的长度,比如两个字符串abcd,abdef,那么它们的最长公共字串为abd,

  长度为3。这个题目它不要求字串连续,其实连续也是一样的,两种dp而已。具体题目如下:

  http://acm.hdu.edu.cn/showproblem.php?pid=1159

思路:

  两个字符串s1,s2。我用dp[i][j]表示s1前i个字符与s2的前i个字符的最长公共字串长度。那么我

  这个值与dp[i-1][j-1 ], dp[i-1][j], dp[i][j-1]的关系是怎样的呢?dp最重要的就是一个状态转移。

  其实不一定是从上面这三个状态转化而来,而是我有这么一个想法,我去比较s1[i]与s2[j],如果

  相等,那么dp[i][j]的长度就是在原来dp[i-1][j-1]的基础上+1,如果不等就是MAX(dp[i-1][j],

  dp[i][j-1])。这个状态转移的正确性是要证明的,这里显然正确O(∩_∩)O~。现在我把一个问题

  已经转化成了它的子问题,其实它是一种递归,只不过它把每次你要递归的值已经保存了下来,也

  就是说,当你要dp[i-1][j-1],dp[i][j-1],dp[i-1][j]的值时,你不用再去递归求解了,这就是一种

  用空间换时间的策略,还有如果当你发现你存的值有些是没用的,那么常常可以进行状态压缩,比

  如,计算最长上升子序列时有两种方法,一种没有进行状态压缩。到最后,递归有一个出口,那么

  dp也要有一个初始值,在这里就是0个字符时,长度为0。

 

  dp就是去想一个状态转移,然后不断去验证,考验的是你的建模能力和分析能力。它解决的一般是

  最优化问题,最大值与最小值等。

  

  我觉得我们要培养计算机的思想,碰到一个问题要想能不能把它分解成几个子问题,这些子问题也

  许是嵌套的,那么就是递归,如果是这个大问题的几个方面,那就把它分开解决,一个函数就实现

  一个功能,不要都把它们揉在一起。还有,必须剔除“找”的观念,计算机只有遍历。

  

代码:

View Code
 1 #include <iostream>
 2 #include <string>
 3 using namespace std;
 4 
 5 int dp[1001][1001];
 6 int main()
 7 {
 8     string s1, s2;
 9     int i, j;
10     while(cin >> s1 >> s2)
11     {
12         int lenX = s1.length();
13         int lenY = s2.length();
14         for(i = 0; i < lenX; i++)
15             for(j = 0; j < lenY; j++)
16             {
17                 if(s1[i] == s2[j])
18                     dp[i+1][j+1] = dp[i][j] + 1 ;//dp[0][j] and dp[i][0] have initialized by 0.
19                 else dp[i+1][j+1] = dp[i+1][j] > dp[i][j+1] ? dp[i+1][j] : dp[i][j+1];
20             }
21             cout << dp[lenX][lenY] << endl;
22     }
23     return 0;
24 }
posted @ 2012-04-21 22:40  可乐爱上了雪碧  阅读(423)  评论(0编辑  收藏  举报