最长公共子序列(LCS)和最优二叉搜索树
来源:互联网 发布:淘宝秋冬裙子 编辑:程序博客网 时间:2024/06/03 11:00
最长公共子序列-------
比较两个串的相似度有这样一种方法:寻找第三个串S3,它的所有序列也都出现在S1 和S2中,且在三个串中出现的次序都相同,但不要求连续出现,可以找到的S3越长就可以认为S1S2相似度越大, 这就是**最长公共子序列**的问题
形式化定义如下:给定一个序列X= {x1,x2..xm},另一个序列Z= {z1,z2,..zk}满足如下条件时称为X的子序列:存在一个严格递增的X的下表序列<i1,i2..ik>对所有j = 1,2,3..k满足 xij = zj。
例如 Z= <B,C,D,B>是X= <A,B,C,B,D,A,B>的一个子序列给定两个序列X和Y,如果Z既是X的子序列也是Y的子序列,则为X和Y的公共子序列
如X= <A,B,C,B,D,A,B>,Y= <B,A,C,F,D,B>,Z= <B,C,D,B>是公共子序列最长公共子序列问题:给定两个序列X,Y求X和Y长度最长的公共子序列(LCS问题)
S1:刻画最长公共子序列
LCS问题具有最优子结构性质,子问题的自然分类对应两个输入序列的”前缀”对;
前缀的严谨定义是:给定一个序列X= {x1,x2..xm},对i = 0,1,...,m定义X的第i前缀为Xi = <x1,x2...xi>
LCS的最优子结构:
令X = <x1,x2...xm>, Y = <y1,y2,..yn>为两个序列,Z = <z1,z2..zk>为X和Y的任意LCS
1、如果xm = yn, 则zk = xm = yn且 Zk-1是 Xm-1 和Yn-1的一个LCS
2、如果xm != yn,那么zk != xm意味着Z是Xm-1和Y的一个LCS
3、如果xm != yn,那么zk != yn意味着Z是X和Yn-1的一个LCS
S2:一个递归解
要求解一个或两个子问题如果xm = yn只要求Xm-1 和Yn-1的一个LCS,然后把xm加到最后如果不等,就要求两个子问题Xm-1和Y的一个LCS,X和Yn-1的一个LCS,找出比较长的一个先从递归的容易思考的角度去想定义c[i , j]表示Xi 和Yj的LCS的长度,如果i = 0 || j = 0,那么LCS长度肯定为0 ,可以得到:
0 i==0|| j==0
c[i , j] = c[i-1 , j-1]+1 i,j>0 && xi = yj
max(c[i, j-1], c[i-1 , j]) i,j>0&&xi!=yj
S3:计算LCS的长度
将递归思想用动态规划实现接受两个序列为输入,将c[i , j]的值保存在表 c[0..m, 0..n]中,并按行主次序计算,过程还维护一个表格b[1..m, 1..n]帮助构造最优解 “X”为 X序列退一步的,‘Y’为Y序列退一步的, ‘D’表示两者最后一个一样,递归找前面的伪代码如下:
```LCS(X,Y)
{ m = X.length; n = Y.length;
let b[1..m, 1..n] and c[0..m, 0..n]be new tables; //一方长度为0时,公共子串长为0
for(int i = 1;i<=m;i++) c[i,0] = 0;
for(int i = 1;i<=n;i++) c[0,i] = 0;
for(int i = 1;i<=m;i++)
for(int j = 1;j<=n;j++)
{if(xi == yj)//最后一个相等
{c[i , j] = c[i-1, j-1]+1; b[i,j] = 'D';}
else if(c[i-1, j]>= c[i, j-1])//X序列退一个与当前Y找的公共串长
{c[i , j] = c[i-1,j]; b[i,j] ='X';}
else {c[i , j] = c[i, j-1]; b[i,j] = 'Y';}
}
return c[], b[];
}```
S4:构造LCS
```Print_Lcs(b, X, i, j)
{ if(i==0||j==0) return;
if(b[i,j]=='D') {Print_Lcs(b,X,i-1,j-1); print xi;}
else if(b[i,j]=='X')Print_Lcs(b,X,i-1,j);
else Print_Lcs(b,X,i,j-1);
}
```起始调用是 (b, X, X.length, Y.length)
最优二叉搜索树
-----------
给定一个n个不同关键字的已排序的序列K=<k1, k2,..kn>,用这些关键字构造一颗二叉搜索树。对每个关键字ki都有一个概率pi表示其搜索频率,有些要搜索的值可能不在k中,因此还有n+1个“伪关键字”d0, d1,d2..dn,d0 表示小于k1的值, dn表示大于kn的值,伪关键字di表示所有在关键字ki ki+1之间的值,每个伪关键字也有对应的qi。通常ki是内部的点,di是叶节点
对一颗搜索树搜索一次的期望为 E[T] = (depth(ki)+1)*pi(i = 1...n 的和)+ (depth(di)+1)*qi(i = 0...n求和)
搜索代价最小的树就是最优二叉搜索树
S1:最优二叉搜索树的结构
一棵最优二叉树包含的子树必然是作为实例的最优结构
S2:一个递归算法
子问题域为求解包含关键字ki..kj的最优二叉搜索树,i>=1&& j>=i-1&&j<=n(j = i-1时子树不包含实际关键字,只包含伪关键字)。定义e[i,j]为包含关键字ki..kj的最优二叉搜索中进行一次搜索的期望代价,最终希望计算出e[1,n]j=i-1的情况最简单,子树只包含伪关键字di-1, e[i, i-1] = qi-1j>=i时,需要从ki...kj中选择一个根节点kr,然后构造一颗包含ki...kr-1的最优二叉搜索树做左子树,kr+1...kj的最优二叉搜索树做右子树。
当一颗子树成为一个结点的子树时,每个结点的深度都增加了1,期望搜索代价的增加值应为所有概率之和对于包含ki...kj的子树,所有概率之和为 w(i,j) = (pl)(l从i到j)+ql(l从i-1到j)因此,若kr为包含关键字ki...kj的最优二叉搜索树的根节点,e[i,j] = pr + e[i,r-1]+w(i,r-1)+e[r+1,j]+w(r+1,j),又 w(i,j) = w(i,r-1)+pr+w(r+1,j)所以e[i,j] = e[i, r-1]+e[r+1,j]+w(i,j)直观上就是左子树的右子树的加上增量
qi-i j=i-1
e[i,j] =
min{e[i,r-1]+e[r+1,j]+w(i,j)} i<=j
S3:计算最优二叉搜索回溯的期望搜索代价
用 root[i,j]来记录这个子树的根对j>=i w[i,j] = w[i, j-1]+pj+qj伪代码如下:
```Optimal_BST(p,q,n)
{ let e[1..n+1, 0..n], w[1..n+1,0..n] root[1..n,1..n]be new tables;
for(i=1;i<=n+1;i++)
{ e[i,i-1] = qi-1; w[i,i-1] = qi-1;}
for(l=1;l<=n;l++)
for(i=1;i<=n-l+1;i++)
{j = i+l-1;
e[i,j] = 1000000000;
w[i,j] = w[i,j-1]+pj+qj;
for(int r = i;r<=j;r++)
{t = e[i,r-1]+e[r+1,j]+w[i,j];
if(t<e[i,j]) {e[i,j] = t; root[i,j] = r;}
} }
}```
- 最长公共子序列(LCS)和最优二叉搜索树
- 算法导论之动态规划(最长公共子序列和最优二叉查找树)
- 最长公共子序列(LCS)
- 最长公共子序列(LCS)问题
- 最长公共子序列(LCS)问题
- 求最长公共子序列(LCS)
- 最长公共子序列算法(LCS)
- LCS(最长公共子序列)
- 最长公共子序列(LCS)问题
- 最长公共子序列(LCS问题)
- Coincidence(LCS最长公共子序列)
- 最长公共子序列(LCS)
- 最长公共子序列(LCS)问题
- 最长公共子序列(LCS)问题
- 最长公共子序列(LCS)
- 最长公共子序列(LCS)
- 最长公共子序列(LCS)
- hdu1243 最长公共子序列(LCS)
- Linux每天一点文件与目录的默认权限与隐藏权限
- IP数据包的格式及分片
- iOS 开发中用pdf图替换png图
- 实习期和试用期
- 富文本控件ueditor
- 最长公共子序列(LCS)和最优二叉搜索树
- 从今晚开始写编程博客
- cocos2d-x 3.x封装socket方法
- Next Permutation
- 安卓6.0权限管理
- 3、在Myeclipse中,导入formatter模板
- 常用删归档,查看归档
- python server简单入门(socket)
- c# wpf 利用截屏键实现截屏功能