动态规划法求解最长公共子序列(含Java代码)
随机字符最长公共子序列递归算法java代码

《随机字符最长公共子序列递归算法Java代码》1. 引言在计算机科学中,最长公共子序列(Longest Common Subsequence,LCS)是一类常见的问题。
它通常涉及字符串处理,其中两个或多个字符串的子序列在不改变顺序的情况下出现在所有给定字符串中的最长序列。
本文将介绍随机字符最长公共子序列的递归算法以及相应的Java代码。
2. 随机字符最长公共子序列递归算法简介随机字符最长公共子序列问题是指对于两个随机字符串,找到它们之间最长的公共子序列。
递归算法是一种常见的解决方法,它通过不断将问题分解为更小的子问题,并对子问题进行求解,从而最终得到原问题的解。
3. 随机字符最长公共子序列递归算法Java代码下面是一个简单的随机字符最长公共子序列递归算法的Java实现:```javapublic class LCS {static int lcs(char[] X, char[] Y, int m, int n) {if (m == 0 || n == 0)return 0;if (X[m - 1] == Y[n - 1])return 1 + lcs(X, Y, m - 1, n - 1);elsereturn Math.max(lcs(X, Y, m, n - 1), lcs(X, Y, m - 1, n)); }public static void main(String[] args) {String s1 = "randomString1";String s2 = "randomString2";char[] X = s1.toCharArray();char[] Y = s2.toCharArray();int m = X.length;int n = Y.length;System.out.println("Length of LCS is " + lcs(X, Y, m, n)); }}```4. 深入理解递归算法递归算法虽然简洁,但有时候可能会导致性能问题,特别是在处理大规模数据时。
动态规划法求解最长公共子序列(含Java代码)

公共子序列问题徐康123183一.算法设计假设有两个序列X和Y,假设X和Y分别有m和n个元素,则建立一个二维数组C[(m+1)*(n+1)],记录X i与Y j的LCS的长度。
将C[i,j]分为三种情况:若i =0 或j =0时,C[i,j]=0;若i,j>0且X[i]=Y[j],C[i,j]=C[i-1,j-1]+1;若i,j>0且X[i] Y[j],C[i,j]=max{C[i-1,j],C[i,j-1]}。
再使用一个m*n的二维数组b,b[i,j]记录C[i,j]的来向:若X[i]=Y[j],则B[i,j]中记入“↖”,记此时b[i,j] = 1;若X[i] Y[j]且C[i-1,j] > C[i,j-1],则b[i,j]中记入“↑”,记此时B[i,j] = 2;若X[i] Y[j]且C[i-1,j] < C[i,j-1],则b[i,j]中记入“←”,记此时B[i,j] = 3;若X[i]Y[j]且C[i-1,j] = C[i,j-1],则b[i,j]中记入“↑”或“←”,记此时B[i,j] = 4;得到了两个数组C[]和B[],设计递归输出LCS(X,Y)的算法:LCS_Output(Direction[][], X[], i, j, len,LCS[]){If i=0 or j=0 将LCS[]保存至集合LCS_SET中then return;If b[i,j]=1 then /*X[i]=Y[j]*/{LCS_Output(b,X,i-1,j-1);将X[i]保存至LCS[len-i];}else if b[i,j]=2 then /*X[i]Y[j]且C[i-1,j]>C[i,j-1]*/LCS_Output(b,X,i-1,j)else if b[i,j]=3 then /*X[i]Y[j]且C[i-1,j]<C[i,j-1]*/ LCS_Output(b,X,i,j-1)else if b[i,j]=4 then /*X[i]Y[j]且C[i-1,j]=C[i,j-1]*/LCS_Output(b,X,i-1,j)LCS_Output(b,X,i,j-1)}二.算法时间复杂度分析由上述对算法的分析得知,求辅助数组C 和B 所消耗的时间复杂度为O (mn ),而查找所有的公共子序列的时间复杂度取决于所遍历的路径,而路径是由算法递归的方向决定的。
最长公共子序列

最长公共子序列GE GROUP system office room 【GEIHUA16H-GEIHUA GEIHUA8Q8-动态规划一、问题描述用动态规划法求两个字符串A=‘xzyzzyx’和B=‘zxyyzxz’的最长公共子序列二、算法分析(1)、若xm=yn,则zk=xm=yn,且Zk-1是Xm-1和Yn-1的最长公共自序列;(2)、若xm≠yn,且zk≠xm,则Zk是Xm-1和Yn的最长公共自序列;(3)、若xm≠yn,且zk≠yn,则Zk是Xm和Yn-1的最长公共自序列;设L(m,n)表示序列X={x1,x2,…,xm}和Y={y1,y2,…,yn}的最长公共子序列的长度L表示已经决策的长度S表示每个决策的状态L(0,0)=L(0,j)=0 1≤i≤m, 1≤j≤nL(i-1,j-1)+1 xi=yi,i≥1,j≥1 L(i,j)=max{L(i,j-1),(L(i-1,j)} xi≠yi,i≥1,j≥1 1 xi=yiS(i,j)= 2 xi≠yi 且L(i,j-1)≥L(i-1,j)3 xi≠yi 且L(i,j-1)< L(i-1,j)长度矩阵L三、源代码#include <iostream>#include <string>using namespace std;int main(){string str1 = "xzyzzyx";string str2 = "zxyyzxz";int x_len = str1.length();int y_len = str2.length();int arr[50][50] ={{0,0}};int i = 0;int j = 0;for(i = 1; i <= x_len; i++){for(j = 1; j <= y_len; j++){if(str1[i - 1] == str2[j - 1]){arr[i][j] = arr[i - 1][j - 1] + 1;}else if(arr[i][j - 1] >= arr[i - 1][j]) arr[i][j] = arr[i][j - 1];elsearr[i][j] = arr[i -1][j];}}for(i = 0 ; i <= x_len; i++){for( j = 0; j <= y_len; j++){cout << arr[i][j] << " ";}cout << endl;}for(i = x_len, j = y_len; i >= 1 && j >= 1;) {if(str1[i - 1] == str2[j - 1]){cout << str1[i - 1] << " ";i--;j--;}else if(arr[i][j -1] > arr[i - 1][j]) j--;elsei--;}cout << endl;return 0;}。
“最长上升子序列,最大连续子序列和,最长公共子串”的Java实现

“最长上升⼦序列,最⼤连续⼦序列和,最长公共⼦串”的Java实现原⽂链接:/xiaoliucool1314/article/details/50963293⼀、问题描述这是三道典型的dp问题。
最长上升⼦序列:在⼀列数中寻找⼀些数,这些数满⾜:任意两个数a[i]和a[j],若i<j,必有a[i]<a[j],这样最长的⼦序列称为最长递增(上升)⼦序列。
设dp[i]表⽰以i为结尾的最长递增⼦序列的长度,则状态转移⽅程为:dp[i] = max{dp[j]+1}, 1<=j<i,a[j]<a[i].时间复杂度为O(n*n);考虑两个数a[x]和a[y],x<y且a[x]<a[y],且dp[x]=dp[y],那么我们该选择哪个呢?显然a[x],因为它更有潜⼒,也就是说我们可以⽤a[x]来替换掉a[y],也就是说我们需要维护⼀个数据结构来存储可能的递增⼦序列的元素,并且需要在某些时候进⾏替换。
因此我们可以⽤⼀个链表来存储,并且在查找替换位置的时候⽤⼆分查找来实现,这样时间复杂度为O(nlogn)。
最⼤连续⼦序列和:在⼀列数中寻找⼀些数,这些数满⾜:任意两个数a[i]和a[j],若i+1=j,必有a[i]<a[j],且∑()最⼤。
需要明确的是状态转移⽅程中的状态代表的含义。
因为contiguous,所以dp[i]代表的应该以i位置元素结尾的连续值,并⾮最⼤值。
最长公共⼦串:两个字符串中的最常公共连续⼦串。
找两个字符串的最长公共⼦串,这个⼦串要求在原字符串中是连续的。
其实这⼜是⼀个序贯决策问题,可以⽤动态规划来求解。
我们采⽤⼀个⼆维矩阵来记录中间的结果。
这个⼆维矩阵怎么构造呢?直接举个例⼦吧:"bab"和"caba"(当然我们现在⼀眼就可以看出来最长公共⼦串是"ba"或"ab") b a bc 0 0 0a 0 1 0b 1 0 1a 0 1 0我们看矩阵的斜对⾓线最长的那个就能找出最长公共⼦串。
最长公共子串(java)

最长公共⼦串(java)关于动态规划:动态规划最重要的是找到可递推的⼦问题,然后列出递推公式,最后搜索填表即可。
表空间⼤⼩⼀般是O(N2)级别。
但⼀般来说,由于递推只与前⼀⾏有关,所以可优化⾄O(N)。
给出两个长度分别为n1, n2的字符串S1, S2, 关于他们的最长公共⼦串,DP⽅程如下:L[i,j] = ( S1[i] == s2[j] ? L[i-1,j-1]+1 : 0 );其中L[i,j]表⽰S1, S2中以第i 和第j 个字符结尾的公共⼦串的长度。
我们把n1 * n2的表空间遍历⼀遍就可得出最长公共⼦串。
代码如下:public String DPlengthOfLongestCommonSubstring(String s1, String s2){if (s1 == null || s2 == null || s1.length() == 0 || s2.length() == 0){return "";}int start = 0;int maxLen = 0;int [][] table = new int[s1.length()][s2.length()];for (int i = 0; i < s1.length(); i++) {for (int j = 0; j < s2.length(); j++) {if (i == 0 || j == 0){if (s1.charAt(i) == s2.charAt(j)){table[i][j] = 1;}if (table[i][j] > maxLen){maxLen = table[i][j];start = i;}}else {if (s1.charAt(i) == s2.charAt(j)){table[i][j] = table[i-1][j-1] + 1;}if (table[i][j] > maxLen){maxLen = table[i][j];start = i + 1 - maxLen;}}}}return s1.substring(start, start + maxLen);} 由于只要填表,⽽后⼀⾏值只与前⼀⾏有关,因此空间可以省到O(N)。
实验四:动态规划策略实现最长公共子序列

for (int i = c[xLen][yLen]; i>0; i--) {
cout << z[i] << " ";
}
cout << endl;
system("pause");
return 0;
}
运行结果:
流程图:
}
else {
i--;
}
}
}
int main() {
cout << "输入第一个序列元素个数:";
cin >> xLen; //下标从i=1开始
cout << "输入长度为"<<xLen<< "的序列:";
for (int i = 1; i <= xLen; i++) {
cin >> x[i];
}
cout << "输入第二个序列元素个数:";
代码:
// zuichanggonggongzixulie.cpp :定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<iostream>
#include<cstring>
usn = 0; //两个子序列的长度
int yLen = 0;
cin >> yLen;
cout << "输入长度为"<<yLen<< "的序列:";
算法55----最长子序列【动态规划】

算法55----最长⼦序列【动态规划】⼀、题⽬:最长公共⼦序列:给定两个字符串,求解这两个字符串的最长公共⼦序列(Longest Common Sequence)。
⽐如字符串L:BDCABA;字符串S:ABCBDAB 则这两个字符串的最长公共⼦序列长度为4,最长公共⼦序列是:BCBA思路:动态规划:时间O(n * m),空间O(n * m)创建 DP数组C[i][j]:表⽰⼦字符串L【:i】和⼦字符串S【:j】的最长公共⼦序列个数。
状态⽅程:个数代码:def LCS(L,S):if not L or not S:return""dp = [[0] * (len(L)+1) for i in range(len(S)+1)]for i in range(len(S)+1):for j in range(len(L)+1):if i == 0 or j == 0:dp[i][j] = 0else:if L[j-1] == S[i-1]:dp[i][j] = dp[i-1][j-1] + 1else:dp[i][j] = max(dp[i-1][j],dp[i][j-1])return dp[-1][-1]L = 'BDCABA'S = 'ABCBDAB'LCS(L,S)最长⼦序列代码:设置⼀个标志def LCS(L,S):if not L or not S:return""res = ''dp = [[0] * (len(L)+1) for i in range(len(S)+1)]flag = [['left'] * (len(L)+1) for i in range(len(S)+1)]if i == 0 or j == 0:dp[i][j] = 0flag [i][j] = '0'else:if L[j-1] == S[i-1]:dp[i][j] = dp[i-1][j-1] + 1flag[i][j] = 'ok'else:dp[i][j] = max(dp[i-1][j],dp[i][j-1])flag[i][j] = 'up'if dp[i][j] == dp[i-1][j] else'left' return dp[-1][-1],flagdef printres(flag,L,S):m = len(flag)n = len(flag[0])res = ''i , j = m-1 , n-1while i > 0 and j > 0:if flag[i][j] == 'ok':res += L[j-1]i -= 1j -= 1elif flag[i][j] == 'left':j -= 1elif flag[i][j] == 'up':i -= 1return res[::-1]L = 'BDCABA'S = 'ABCBDAB'num,flag = LCS(L,S)res = printres(flag,L,S)⼆、题⽬:最长递增⼦序列8},则其最长的单调递增⼦序列为{5,6,7,8},长度为4.解法⼀:最长公共⼦序列:O(N^2)这个问题可以转换为最长公共⼦序列问题。
最长公共子序列 输出序列 java

最长公共子序列(Longest Common Subsequence,简称LCS)是一种经典的字符串匹配问题,其主要目的是在两个字符串中找到最长的公共子序列。
LCS问题在计算机科学中有着广泛的应用,例如文本比较、DNA分析、语音识别等领域。
本文将介绍如何使用动态规划算法解决LCS问题,并给出Java代码实现。
同时,我们将通过一个实际的例子来说明LCS问题的解法。
一、问题描述给定两个字符串s1和s2,找出它们的最长公共子序列。
例如,对于字符串s1="ABCDGH"和s2="AEDFHR",它们的最长公共子序列为"ADH",长度为3。
二、问题分析对于LCS问题,我们可以使用动态规划算法来解决。
具体思路如下:1. 定义状态我们定义dp[i][j]表示s1[0:i]和s2[0:j]的最长公共子序列的长度。
其中,s1[0:i]表示s1中从0到i 的子串,s2[0:j]表示s2中从0到j的子串。
2. 初始化当i=0或j=0时,dp[i][j]均为0。
因为此时s1[0:i]或s2[0:j]为空字符串,它们之间没有任何公共子序列。
3. 状态转移方程当s1[i-1]==s2[j-1]时,说明s1和s2的最后一个字符相同,因此它们的最长公共子序列长度应该加1。
即:dp[i][j] = dp[i-1][j-1] + 1当s1[i-1]!=s2[j-1]时,说明s1和s2的最后一个字符不同,此时有两种情况:- 最长公共子序列包含s1[i-1],不包含s2[j-1],即dp[i][j] = dp[i-1][j];- 最长公共子序列包含s2[j-1],不包含s1[i-1],即dp[i][j] = dp[i][j-1];因此,我们可以得到状态转移方程:dp[i][j] = max(dp[i-1][j-1]+1, dp[i-1][j], dp[i][j-1])其中,max函数表示取三个数中的最大值。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
公共子序列问题徐康123183一.算法设计假设有两个序列X和Y,假设X和Y分别有m和n个元素,则建立一个二维数组C[(m+1)*(n+1)],记录X i与Y j的LCS的长度。
将C[i,j]分为三种情况:若i =0 或j =0时,C[i,j]=0;若i,j>0且X[i]=Y[j],C[i,j]=C[i-1,j-1]+1;若i,j>0且X[i] Y[j],C[i,j]=max{C[i-1,j],C[i,j-1]}。
再使用一个m*n的二维数组b,b[i,j]记录C[i,j]的来向:若X[i]=Y[j],则B[i,j]中记入“↖”,记此时b[i,j] = 1;若X[i] Y[j]且C[i-1,j] > C[i,j-1],则b[i,j]中记入“↑”,记此时B[i,j] = 2;若X[i] Y[j]且C[i-1,j] < C[i,j-1],则b[i,j]中记入“←”,记此时B[i,j] = 3;若X[i]Y[j]且C[i-1,j] = C[i,j-1],则b[i,j]中记入“↑”或“←”,记此时B[i,j] = 4;得到了两个数组C[]和B[],设计递归输出LCS(X,Y)的算法:LCS_Output(Direction[][], X[], i, j, len,LCS[]){If i=0 or j=0 将LCS[]保存至集合LCS_SET中then return;If b[i,j]=1 then /*X[i]=Y[j]*/{LCS_Output(b,X,i-1,j-1);将X[i]保存至LCS[len-i];}else if b[i,j]=2 then /*X[i]Y[j]且C[i-1,j]>C[i,j-1]*/LCS_Output(b,X,i-1,j)else if b[i,j]=3 then /*X[i]Y[j]且C[i-1,j]<C[i,j-1]*/ LCS_Output(b,X,i,j-1)else if b[i,j]=4 then /*X[i]Y[j]且C[i-1,j]=C[i,j-1]*/LCS_Output(b,X,i-1,j)LCS_Output(b,X,i,j-1)}二.算法时间复杂度分析由上述对算法的分析得知,求辅助数组C 和B 所消耗的时间复杂度为O (mn ),而查找所有的公共子序列的时间复杂度取决于所遍历的路径,而路径是由算法递归的方向决定的。
显然,最好的情况是m=n 并且B 中的所有值都为1(按斜对角线方向搜索),此时时间复杂度为O (n )。
当X 和Y 序列不存在公共子序列时为算法的最坏情况,因为此时C 数组的所有元素都为0,B 在每一个节点都要沿着两个不同的方向搜索,即每次都要调用两次LCS_Output,当调用到i=0或j=0时返回,直到搜索完整个m*n 数组才结束。
该时间复杂度就是计算从点(m,n )到i=0或j=0的所有路径。
建立如上图的直角坐标系,设点S (m ,n ),x 轴上的坐标点P 1(1,0) 到Pm(m,0),y 轴上的系列坐标点Q 1(0,1) 到Qn(0,n)。
因为j i Q P 和是搜索路径的边界上的点,点1+i P 不能直接到达点i P ,点1+j Q 也不能直接到达j Q ,所以点),(n m S 到m i P P P P ,...,,...,,21和n j Q Q Q Q ,...,,...,,21的路径数等价于),(n m S 到点)1,('),...,1,('),...,1,2('),1,1('21m P i P P P m i 和点),1('),...,,1('),...,2,1('),1,1('21n Q j Q Q Q n j 的路径数,又因为点),(n m 到),(j i 路径数为in j i n m C ---+,设总路径数为t ,则有()()m mn n m n n m n n m n m m n n m n n n m m n m m n m m n m n n m n mj jm jm n ni in in m C C C C C C C C C C C C C C C Ct ++-+--+--+--+---+--+---+--+=--+-=--+-===+=+=+++++++++=+=∑∑1111111011231201123121111...... 三.程序流程图如下所示四.程序源码package Homework2;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.HashSet;import java.util.Set;public class LCS {int C[][];int B[][];Set LCS_SET = new HashSet(); //使用集合去重public int LCSLength(char X[], char Y[]) { //返回公共子序列长度int m = X.length;int n = Y.length;C = new int[X.length][Y.length];B = new int[X.length][Y.length];for (int i = 0; i < m; i++) {C[i][0] = 0;B[i][0] = 0;}for (int j = 0; j < n; j++) {C[0][j] = 0;B[0][j] = 0;}for (int i = 1; i < m; i++) {for (int j = 1; j < n; j++) {if (X[i] == Y[j]) {C[i][j] = C[i - 1][j - 1] + 1;B[i][j] = 1;} else if (C[i - 1][j] > C[i][j - 1]) {C[i][j] = C[i - 1][j];B[i][j] = 2;} else if (C[i - 1][j] < C[i][j - 1]) {C[i][j] = C[i][j - 1];B[i][j] = 3;} else {C[i][j] = C[i - 1][j];B[i][j] = 4;}}}return C[m - 1][n - 1];}public void LCS_Output(int Direction[][], char X[], int i, int j, int len, char LCS[]) {int lcslen = len;if (i == 0 || j == 0) {LCS_SET.add(String.valueOf(LCS));return;}if (B[i][j] == 1) {LCS[len - 1] = X[i];len--;LCS_Output(B, X, i - 1, j - 1, len, LCS);} else if (B[i][j] == 2) {LCS_Output(B, X, i - 1, j, len, LCS);} else if (B[i][j] == 3) {LCS_Output(B, X, i, j - 1, len, LCS);} else if (B[i][j] == 4) {LCS_Output(B, X, i - 1, j, len, LCS);LCS_Output(B, X, i, j - 1, len, LCS);}}/***@param args*/public static void main(String[] args) throws IOException { // TODO Auto-generated method stubchar X[], Y[];BufferedReader buf = null;buf = new BufferedReader(new InputStreamReader(System.in));System.out.println("请输入一个序列");X = buf.readLine().toCharArray();char X_temp[] = new char[X.length + 1];for (int i = 0; i < X.length; i++) {X_temp[0] = ' ';X_temp[i + 1] = X[i];}System.out.println("请输入一个序列");Y = buf.readLine().toCharArray();char Y_temp[] = new char[Y.length + 1];for (int i = 0; i < Y.length; i++) {Y_temp[0] = ' ';Y_temp[i + 1] = Y[i];}System.out.print("X=");for (char x : X) {System.out.print(x);}System.out.println();System.out.print("Y=");for (char y : Y) {System.out.print(y);}System.out.println();LCS lcs = new LCS();int len = lcs.LCSLength(X_temp, Y_temp);char LCS[] = new char[len];int m = X.length;int n = Y.length;System.out.println("最长公共子序列长度为:" + len); // 输出最长子序列长度System.out.print("最长公共子序列有:");lcs.LCS_Output(lcs.B, X_temp, m, n, len, LCS);System.out.print(lcs.LCS_SET); // 输出子序列集合中的元素}}五.运行结果截图1.输入abc和acb2.输入asd和xcv3.输入ABCBDAB 和BDCABA经检查输出结果均正确!。