最长连续公共子序列(LCS)与最长递增公共子序列(LIS)
最长公共子序列(不连续)
实际问题中也有比较多的应用,比如,论文查重这种,就是很实际的一个使用方面。
这个应该是最常见的一种了,不再赘述,直接按照转移方程来进行:
按最普通的方式就是,直接构造二维矩阵,两个序列分别是Ai 以及 Bj ,c[i,j]就表示的是第一个序列的从开始到第Ai个元素,以及第二个序列的从开始到第Bj个元素,这两部分序列的最长的公共子序列,如果ai==bj,则斜对角加1,否则就是前面和上面的元素中最大的那一个,就是按照这种方式,一层层的向下递推。
最长连续公共子序列
就是strict-LCS的情形,
这里c[I,j]的定义与原来有所不同,这里的才c[I,j]指的是最后一个元素为xi时候,并且xi==yj时候的的长度。
不论前面的情况如何,如果xi与yj不相等,就将c[I,j]归为0 其实转移方程也还是比较简易的:
就是把累加性的部分去掉就好了。
PAT1040
这个最终也可以转化成LCS的思路来求解 如果一个序列中间有连续的对称部分的话 不过这个是最长连续的公共子序列。
最长递增公共子序列
1045
这个是比较典型的
这个可以有多种解法
一个是转化成LCS,一个是就用最本来的LIS的递归的方法,可以参考这个:
http://blog.csdn.net/joylnwang/article/details/6766317
其实转化成LCS,可以算成一种变形:
http://blog.csdn.net/tiantangrenjian/article/details/19921051
这个可以算成是公共部分可以重复的最长公共子序列,但是这个重复的部分也应该是其中某个序列中的,整体来说,就是这个题目的背景。
这个时候递归的时候:
还是通过矩阵向后递推,只是:
先要求出max元素,如果当前的元素是c[I,j],那么c[i-1][j] c[I,j-1] c[i-1,j-1]中的最大一个,把它称为max元素,通常像这样:
1. max = len[i-1][j-1];
2. if(max < len[i][j-1])max = len[i][j-1];
3. if(max < len[i-1][j])max = len[i-1][j]; //先求出左边、上边、左上边 三个值中的最大值
A[i]=B[j]的时候 直接才c[I,j]=max+1
A[i]!=B[j]的时候 直接c[I,j]=max
注意这里直接放成max 根据max往后走。
对于这个题,还是用这种方法比较好,要是用最简单的LCS就是按照color出现的顺序来对原来的stripe进行排序,并且将没有出现的元素滤去,这样需要申请m[N][N]的空间,题中的N给的比较大,很可能超时。
LCS的递归不像背包问题的那种,可以用一行来结局,要是用两行的话,就得不断的把之前的一行保存下来,这里N的时候,又是容易发生超时。