ImageVerifierCode 换一换
格式:DOCX , 页数:15 ,大小:66.83KB ,
资源ID:12782706      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/12782706.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(算法LCS所有的最长公共子序列.docx)为本站会员(b****0)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

算法LCS所有的最长公共子序列.docx

1、算法LCS所有的最长公共子序列 所有的最长公共子序列(LCS)一、 问题描述子序列的概念: 设X = ,若有1i1i2 ikm,得Z= = ,则称Z是X的子序列,记为ZX。e.g. X=, Z=, 则有ZX。公共子序列的概念:设X,Y是两个序列,且有ZX和ZY,则称Z是X和Y 的公共列。最长公共子序列的概念:若ZX,ZY,且不存在比Z更长的X和Y 的公共子序列,则称Z是X和Y 的最长公共子序列,记为Z LCS(X , Y)。但是LCS不是只有一个,最长公共子序列往往不止一个。e.g. X=, Y=, 则Z=, Z=, Z=均属于LCS(X , Y) ,即X,Y有3个LCS。本文描述如何寻找所有

2、的LCS二、问题分析先描述寻找一个LCS的思想:记Xi=x1,xi即X序列的前i个字符 (1im)(前缀)Yj=y1,yj即Y序列的前j个字符 (1jn)(前缀)假定Z=z1,zkLCS(X , Y)。若xm=yn(最后一个字符相同),则不难用反证法证明:该字符必是X与Y的任一最长公共子序列Z(设长度为k)的最后一个字符,即有zk = xm = yn。且显然有Zk-1LCS(Xm-1 , Yn-1)即Z的前缀Zk-1是Xm-1与Yn-1的最长公共子序列。若xmyn,则亦不难用反证法证明:要么ZLCS(Xm-1, Y),要么ZLCS(X , Yn-1)。由于zkxm与zkyn其中至少有一个必成立

3、,因此:若zkxm则有ZLCS(Xm-1 , Y),若zkyn 则有ZLCS(X , Yn-1)。 若xm=yn,则问题化归成求Xm-1与Yn-1的LCS,(LCS(X , Y)的长度等于LCS(Xm-1 , Yn-1)的长度加1) 若xmyn,则问题化归成求Xm-1与Y的LCS及X与Yn-1的LCSLCS(X , Y)的长度为:Max LCS(Xm-1 , Y)的长度, LCS(X , Yn-1)的长度求LCS(Xm-1 , Y)的长度与LCS(X , Yn-1)的长度这两个问题不是相互独立的:两者都需要求LCS(Xm-1,Yn-1)的长度,因而具有重叠性。此外,两个序列的LCS中包含了两个

4、序列的前缀的LCS,故问题具有最优子结构性质 考虑用动态规划法。引进一个二维数组C,用Ci,j记录Xi与Yj的LCS的长度。 如果我们是按行、列的序号从小到大地进行递推计算,(从第1行开始计算:C1,1、C1,2、。C1,n,再算C2,1、C2,2、。C2,n,。最后计算Cm,1、Cm,2、。Cm,n,最后算出的Cm,n即为LCS(X , Y)的长度。)那么在计算Ci,j之前,Ci-1,j-1, Ci-1,j与Ci,j-1均已计算出来。此时根据Xi=Yj还是Xi Yj,就可以计算出Ci,j:若Xi=Yj,则执行Ci,jCi-1,j-1+1;若Xi Yj,进行下述判断:若Ci-1,jCi,j-1

5、则Ci,j取Ci-1,j;否则Ci,j取Ci,j-1。即有Ci,j=为了构造出LCS,使用一个m n的二维数组b,bi,j记录Ci,j是通过哪一个子问题的值求得的,以决定搜索的方向:若Xi=Yj,则bi,j中记入“”(亦可不记);若Xi Yj且Ci-1,j Ci,j-1,则bi,j中记入“”;若Xi Yj且Ci-1,j Ci,j-1,则bi,j中记入“”;e.g. 对于X=,Y=,求出的各个Ci,j与bi,j如下图: 0 1 2 3 4 5 6 yj B D C A B A0 xi 0 0 0 0 0 0 0 1 A 0 0 0 0 11 1 2 B 0 111 1 22 3 C 0 1 1

6、2 2 2 2 4 B 0 1 1 2 2 33 5 D 0 1 2 2 2 3 3 6 A 0 1 2 2 3 3 4 7 B 0 1 2 2 3 4 4找出所有路径的思想:仅用“” ,“” ,“”是搜索不到所有的LCS的,因为Ci-1,jCi,j-1,我们没有区分Ci-1,jCi,j-1还是Ci-1,jCi,j-1此时我们只是在单方向搜索,就像是图的深度优先搜索,走到底,找出一条路径。为了找出所有的LCS,我们将Ci-1,jCi,j-1记做“”。同时用遍历bi,j构造出一棵树tree,“”的方向记做节点的左子树,右子树为空,“”的方向记做节点的右子树,左子树为空,“”的方向开辟新的节点,并

7、对其赋值,“”记做节点的左子树和右子树。当树构造完毕时,我们从叶子节点开始遍历,一直到根为止,即找出所有的LCS。注意:此时找出的所有的LCS可能有重复的,所以用一个字符串数组来记录不同的LCS。容易证明该字符数组最长为minx.length,y.length;三、解决方案 为了方便,程序中将“” 记做1,“”记做-1 ,“”记做0,“”记做2./treenode.h#ifndef TREENODE_H#define TREENODE_Hclass TreeNode friend class tree;public: TreeNode(char a=0) /构造函数 data=a; leftc

8、hild=0; rightchild=0; parent=0; TreeNode * leftchild; TreeNode * rightchild; TreeNode* parent; /从叶子往根遍历时找的路线 char data; ;#endif/构造树/tree.h#ifndef TREE_H#define TREE_H#include treenode.h#include #include stack.hconst int m=7,n=6; /默认x的长度为7,y的长度为6int i=0,j=0;int exsit=0; /记录字符串数组有几个元素class treepublic:

9、 tree(int bm+1n+1,string x,int i,int j); TreeNode* LCS(int bm+1n+1,string x,int i,int j);/构造树 void inorder(); void inorder(TreeNode*);/中序遍历,找出所有的叶子节点 void con_parent();/遍历树,找出每个节点的parent void tranverse(TreeNode*);/从叶子节点遍历到根,找出LCS void output(); /输出所有的LCSprivate: TreeNode *root;/根 Stack stack;/用栈来记录叶

10、子节点 string *t;/字符串数组记录不同的LCS;tree:tree(int bm+1n+1,string x,int i,int j) t=new stringn;/字符串数组最长为minx.length,y.length for (int y=0;yleftchild=LCS(b,x,i-1,j-1);/左子树继续构造 return a; else if (bij=1) return LCS(b,x,i-1,j);/往上面走,不创造新节点,继续递归 else if (bij=-1) return LCS(b,x,i,j-1);/往左面走,不创造新节点,继续递归 else /遇到两个

11、方向的点,创造新节点,并默认赋值为#,递归构造 左子树和右子树。 TreeNode* a=new TreeNode(#); a-leftchild=LCS(b,x,i-1,j); a-rightchild=LCS(b,x,i,j-1); return a; void tree:inorder() inorder(root);/找出所有的叶子节点用栈来记录void tree:inorder(TreeNode* current) if(current) inorder(current-leftchild); if(current-data=#) stack.add(current); inorde

12、r(current-rightchild); 遍历树,找出每个节点的parentvoid tree:con_parent() int i=0; Stack s; TreeNode* currentNode=root; while(1) while(currentNode) s.add(currentNode); TreeNode* pp=currentNode; if (currentNode-leftchild) currentNode-leftchild-parent=pp; currentNode=currentNode-leftchild; if (s.IsEmpty() return

13、; currentNode=s.Top(); coutdatarightchild) currentNode-rightchild-parent=pp; currentNode=currentNode-rightchild; /从叶子遍历到根,找出LCSvoid tree:tranverse(TreeNode* leaf) TreeNode* currentNode=leaf; string temp=; bool flag=true; while(currentNode-parent) if (currentNode-data!=#¤tNode-data!=$) temp=tem

14、p+currentNode-data+ ; currentNode=currentNode-parent; if(root-data!=#)/若根有非真值添加到其中去 temp+=root-data; /看LCS若有重复的,不存入string数组中, for (int count=0;countm;count+) if (temp=tcount) flag=false; break; if (flag) couttempn; texsit+=temp; temp=; flag=true;/找出所有的LCSvoid tree:output() while(!stack.IsEmpty() tra

15、nverse(stack.Top(); #endif/test.cpp 测试函数#include using namespace std;#include tree.hint main() int bm+1n+1; int cm+1n+1; string x= abcdefg; string y= fedcba; int i,j; for(i=0;i=m;i+) ci0=0; bi0=0; for (j=1;j=n;j+) c0j=0; b0j=0; /构造出cij,bij for (i=1;i=m;i+) for (j=1;jcij-1) cij=ci-1j; bij=1; else if (ci-1jcij-1) cij=cij-1; bij=-1; else cij=ci-1j; bij=2; tree t(b,x,7,6); /构造树 t.con_parent();/找出每个节点的parent t.inorder();/找出所有的叶子节点 t.output();/输出所有的LCS return 0;四、输出结果X=, Y=X= y= x=,y=五、性能分析显然,构造二维数组b,c时间为;构造树时间,T(n)=2T(n-1)时间为O;找出parent节点的时间为O(logn),从叶子遍历到根时间为O(logn);该算法复杂度为O.性能不好。

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1