训练第三周之dp-序列

本篇纯属抄袭协会ppt,以求以后能随时回顾。


1、最长递增子序列(LIS)

概念:

子串:指给定字符串中选取的某一连续的段

子序列:可以不连续,但是要保证原字符串的顺序

例:给定字符串{A,B,C,D,E}

{A,B,C}既是子串,又是子序列。
{A,C,E}仅为子序列。

最长递增子序列:即子序列的元素是递增的。

求法:

假设有x个元素组成的序列,以第i个元素结尾的最长递增子序列长度为dp[i]。此时在序列末加上第x+1个元素,那么dp[x+1]=?

例:有一个序列{1,3,5,2}。
以1结尾的LIS只有{1},dp[1]=1。
以3结尾的LIS有{3}{1,3},dp[2]=2。
以4结尾的LIS有{5}{1,5}{3,5}{1,3,5},dp[3]=3。
以2结尾的LIS只有{2}{1,2},dp[4]=2
那么如果序列末加上元素4,dp[5]如何由已知的dp[1],dp[2],dp[3],dp[4]得到呢?

首先,以4结尾的子序列一定有{4},所以dp[5]=1先与第一个元素比较,4>1,以1结尾的最大递增子序列末尾加上元素4,构成新的子序列也一定是递增的。所以dp[5]=max{dp[5],dp[1]+1}而当与第三个元素比较,4<5,不能在以5结尾的LIS的基础上构成新的LIS,所以不更新dp[5]的值。

由此可以得出状态转移方程为dp[i]=max{dp[i],dp[j]+1}(a[i]>a[j]&&i>j)

伪代码:

For i=1…n
       dp[i]=1
   For i=1...n
       For j=1...i-1
           if a[i]>a[j]
               dp[i]=max(dp[i],dp[j]+1)

2、最长公共子序列(LCS)

概念:

定义:给定两个序列,求他们相同的子序列中最长的长度。

例如:X={A,B,C,B,D,A,B},Y={B,D,C,A,B,A}。肉眼可以看出其中一个LCS={B,D,A,B}(不唯一),长度为4。

如何求解?

首先我们定义dp[i][j]=LCS{X[1…i],Y[1…j]}在已知dp[i-1][j-1],dp[i-1][j],dp[i][j-1]的情况下,怎么求解dp[i][j]?

如果x[i]=y[j],dp[i][j]=dp[i-1][j-1]+1假设z[1…k]=LCS{X[1…i],Y[1…j]},那么z[k]=x[i]。为什么?反证法。那么z[1…k-1]=LCS{X[1…i-1],Y[1…j-1]},即dp[i-1][j-1]

如果x[i]!=y[j],dp[i][j]=max{dp[i-1][j],dp[i][j-1]}

训练第三周之dp-序列_第1张图片

求最长公共子串也差不多:

if(xi==yj) dp[i][j]=dp[i-1][j-1]+1;

else dp[i][j]=0;

3、连续子序列最大和:

if(dp[i-1]>0) dp[i]=dp[i-1]+a[i];如果dp[i-1]>0,那么dp[i-1]+a[i]>a[i]

else dp[i]=a[i];否则一定小于a[i]

你可能感兴趣的:(acm集训日志,dp)