最长公共子序列问题.docx
- 文档编号:27968261
- 上传时间:2023-07-06
- 格式:DOCX
- 页数:10
- 大小:104.65KB
最长公共子序列问题.docx
《最长公共子序列问题.docx》由会员分享,可在线阅读,更多相关《最长公共子序列问题.docx(10页珍藏版)》请在冰豆网上搜索。
最长公共子序列问题
实验三最长公共子序列问题
1.实验环境
本实验采用java语言编写实现,环境:
,编译器:
eclipse
2.实验目的
通过最长公共子序列问题,巩固并详细分析动态规划思想和解题步骤。
最长公共子序列的定义为:
设有两个序列Si[1..m]和84仁n],需要寻找它们之间的一个最长公共子序列。
例如,假定有两个序列:
81:
INTHEBEGINNING
82:
ALLTHING8ARELO8T
则8i和S的一个最长公共子序列为THING又比如:
81:
ABCBDAB
82:
BDCABA
则它们的一个最长公共子序列为BCBA。
这里需要注意的是,一个子序列不一定必须是连续的,即中间可被其他字符分开,单它们的顺序必须是正确的。
另外,最长公共子序列不一定只有一个,而我们需要寻找的是其中一个。
当然,如果要求子序列里面的元素必须连成一片也是可以的。
实际上,连成一片的版本比这里实现的更容易。
4.过程
我们可以通过蛮力策略解决这个问题,步骤如下:
1.检查S1[1..m]里面每一个子序列。
2.看看其是否也是S2[1..n]里的子序列。
3.在每一步记录当前找到的子序列里面最长的子序列。
这种方法的效率十分低下。
因此本实验采用动态规划的方法实现该算法。
利用动态规划寻找最长公共子序列步骤如下:
1.寻找最长公共子序列的长度。
2.扩展寻找长度的算法来获取最长公共子序列。
策略:
考虑序列S1和S2的前缀序列。
设c[i,j]=|LCS(S1[1..i],S2[1..j]),则有c[m,n]=|LCS(S1S2)|
所以有
c[i,j]=
如果S1[i]工S2[j]
max{c[i-1,j],c[i,j-1]},
然后回溯输出最长公共子序列过程:
0
0
0
0
0
0
0
0
t
0
t
0
T
0
\
I
—1
、
1
0
\
1
]
—1
1
\
7
計
T
1
T
1
2
r
T
\
I
T
1
牛■
11
2
\
3
—3
0
1
I
\
2
T
2
t
3
0
TI
r
1
T
2
3
\
4
0
\
1
T
\
4
'T
4
A
B
D
叫〃CAB4
5.实现源代码
packageIcsimple;
publicclassLCSImplem{
断点调试及代码分析
首先在main方法里定义两个字符串,如:
stringstrl='*ABCBDAB*';
Stringstu2=caba";
对这两个字符串,使它们的第一个字符为空,即初始化之后的c[][]的第一行第一列,之所以要空出,是因为c[][]代表的是两个字符串数组多少个,0的意思就是某个字符串的长度为0。
然后将这两个字符
串分割为char型数组:
Stri=E»十stri;
str2三+str2;
Gha.r[]fitringArrl=stri.toC:
harArra.y(J;char[]stringArr2=str2.toCharArray(};
接下来就调用getLength方法计算出决定搜索方向的数组,传到该
方法的两个数组参数stringArrI和stringArr2的值可以看到
Value
(iid=16}
然后定义两个二维数组b[][],c[][],大小为*,用于接受结果矩阵。
int[][]b=newinh[stringArrl.length)[stringArrl2.length);
int[][]c=newinh[striiigAcr1.length][stringArrl2.length;;
上——I——J-—*1.J■——-n-1~1_1.1_--L■■br
接着遍历每一个stringArrI的值,与stringArr2的每一个值做比较:
foE(inti=l;i<£tringAi;rl,l&ngtti;i++】{for(Intj=1;j riiigArrl2.length;j++}{frn-■r■T叶・I—I 缀序列为后面的匹配计算使用,将当前值赋值为1,b[i][j]用于保存匹 配结果记为1: =吕2【j]的情说 if[stzingArrl[i]=string貝rr12[j]){ C[i][j]=G[i-i][j-1]+1;b[i][j]=1; 把下面的两个判断作为第二层判断,即当当前字符不匹配的时候 对c[i][j]做计算,c[i][j]就是该值在矩阵中上面一个数和左边一个数中较大的值: ."■51[丄]¥£2(泊的情况 elseif(G[i=l][j]>二c[il[j一1]〕{Ci][j]=c[i-lj[j]; bfi]tjI=0; else{ [j]=c[i] [j]=-1; 这些判断就是对该矩阵值的计算,c矩阵: 但是这个方法返回的是b矩阵,b矩阵在当前位置在字符匹配时的值为1,不匹配时,就对c矩阵做出比较,该值在矩阵中左边的数值大于上边的数值时,b矩阵在当前位置在字符匹配时的值为0,反 之记为-1。 因此,计算返回b矩阵,输出b矩阵 for(inti=0;i for(intj=J;j System-out.printIn(); 得到: Display[Y: r,stringArr1.length-l,strirLqArr2.1昌ngth—1); /归耳瘁d弘用蟄H prlvatsstiticvoidDisplav(intf]flb,char[1strinqArr1,intIntj)[if(i==0IIJ=0)i return; ±f(b[i3[j]=1)4 Display(b,stringFire1,i-l,;-1H System,out.print(? ': z.ringArrL[iJ+""]; 吐j"if(b[iJ[J]=0){ PiffpJistrir.: iArrl,i-i,i)j elseif(b[i1(j]=-1>f 当当前值为1时,说明字符匹配成功,再对左上方的值进行比较; 当当前值为0时,说明左边的值大于上边的值,采用递归法,再对上边的值进行比较;当当前值为-1时,对左边的值进行比较。 下面是对 b的迭代: 3S sa returriF System.outrprintln(i+'*==>*+j); If(btij(j]=1}{ nJspJavtb,BrrzLnqAxrL,i—1,i—1); I二二Prrp(Mi*KSprvwDpt”Sourr*F、plo仲f匕.^nrppstc曰Comfol* termirdiedLCSImpIcru[JavaAppIicjtkjrtlD;\jJk_1,fl^jdk_13\bin\ijvj-^VrCAc(2017^12^5E E==J>€ b==>i 4==>i 3==>^ 3==>a| 2==>2 2=61 这个方法,就是对下面矩阵方向的计算: 0 0 0 0 0 0 0 0 T 0 T 0 Tf) 、 1 —1 \ I 0 \ 1 —1 —1 t 1 \ 2 r 0 T 1 1 1 \ 2 — T — 0 \ 1 T 1 T 2 T 2 、 —3 T \ r T t T 0 J 2 2 2 3 3 0 T 1 2 \ 3 T 3 \ 4 0 \ 1 T 1 \ 4 片 A B B D A H $1RDCABA O' -I丄 最后输出判断中匹配上的结果。 7. rH 算法分析 由于每次调用至少向上或向左(或向上向左同时)移动一步,故最多调用(m*n)次就会遇到i二0或j=0的情况,此时开始返回。 返 回时与递归调用时方向相反,步数相同,故算法时间复杂度为0(m* 8.实验结果 在main方法中输入的字符串为: -LPV7丄"UwdXX1丄■七 Stringstrl= StringsZr2="bdcaba"; 所以得到结果: crerminated;BCEA 改变输入的字符串测试: HUJJ亠亠JnJdV■亠Vmn丄J,二\7XLJ 50 51 Stringstrl="ABCBDABEFEV'";Stringstr2=BDCABAEFTcf*; £2MarkersDProperties鼎Servers理DataSourceEicploreribSnippe吒terminatedALCSlmplem(JdvaAppikationjD;^dk_1,8\jdk_1.fl\bin\jdvaw.exeBCEAEF 结果准确,实验结束。 9.实验总结 对最长公共子序列的求解,实际上是对动态规划思想的学习,这 个实验实现的算法比前两个实验实现的算法难度又有所提升,对字符 串进行反复递归时容易出错,所以只能先对简单的字符串计算进行测 试。 个人认为,动态规划思想中难的部分就是突出在反复的循环/递归,对循环参数的取值往往让人伤神,需要十分谨慎小心,并反复的测验才能确保算法的正确性。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 最长 公共 序列 问题