最长公共子序列(动态规划) nyoj36

来源:互联网 发布:linux查看用户属性 编辑:程序博客网 时间:2024/06/06 07:00

  最长公共子序列也称作最长公共子串(不要求连续),英文缩写为LCS(Longest Common Subsequence)。

  做了一些动态规划的题的同学应该知道 做这类题大多是通过自底向上(或自顶向下)的方式求出每一状态的最优 解,

 最后得出问题的最优解。(一般用数组(或别的)存它的当前状态下的最优解,求当前状态如果需要由之前的状态 求得时,直接用就可以了)

   现在我们就以串 A:a s d f  串 B:a d f s d 这两个串为例, 做一下最长公共子序列。

(1)自顶向下:


                    d[i][j] = d[i-1][j-1] + 1;        A[i] =B[j]    

LCS(I, j) =  d[i][j]= max(d[i-1][j], d[i][j-1])  A[i]≠B[j]  


d[i][j]代表 A中前i个字符与B中前j个字符的最长公共子序列的值,

当A[i]与B[j]相等时,那么d[i][j] 就等于d[i-1][j-1] + 1(应为每一个状态存的都是当前最优解,d[i-1][j-1]+1一定是d[i][j]的最优解);

当A[i]与B[j]不相等时,那么就往前一状态看,等于前一状态,d[i][j]的前一状态有两个①d[i][j-1](A中前i个与B中前j-1个的状态)②d[i-1][j](A中前i-1个与B中前j个的状态),所以d[i][j]= max(d[i-1][j], d[i][j-1]);

看图分析一下:

d[3][3] : 可以看做是d[asd][adf] = max(d[asd][ad], d[as][adf]);

d[4][3]:  可以看成d[asdf][adf] = d[asd][ad] + 1;  (希望可以看懂!!)

 


012340
asdf1a11112d11223f11234s12235d1233

 

ny36题

 

 

(2)自底向上

和第一种方法差不多, 就是方向问题, 第一个看明白了, 这个就很容易看懂了(这个用了递归),

当求d[i][j]时 如果A[i]=B[j] , 那么就由 d[i-1][j-1]这一状态求得; 如果A[i]!=B[j] , 那么他就应该是由 d[i-1][j] 和d[i][j-1]求得。


注:下图是两个串x:ABCBDAB  y:BDCABA(这个图是截的图)

 

 

代码附上

好好理解一下!!!

0 0
原创粉丝点击