最長公共子序列(JAVA)
最長公共子序列問題:若給定序列X={x1,x2,…,xm},則另一序列Z={z1,z2,…,zk},是X的子序列是指存在一個嚴格遞增下標序列{i1,i2,…,ik}使得對於所有j=1,2,…,k有:zj=xij。例如,序列Z={B,C,D,B}是序列X={A,B,C,B,D,A,B}的子序列,相應的遞增下標序列為{2,3,5,7}。
給定2個序列X和Y,當另一序列Z既是X的子序列又是Y的子序列時,稱Z是序列X和Y的公共子序列。
總結起來就是:1.最長公共子序列中的元素是要倆個序列共有的。
2.這些元素在原序列的下標必須的遞增的。
用動態規劃的思路去求解會節約許多時間,可以先求出最長公共子序列的長度,再去求出對應的值。
void LCSLength (char x[] ,char y[], int m, int n, int c[][], int b[][])
{
int i,j;
for (i = 1; i <= m; i++) c[i][0] = 0;//第0列設為0
for (i = 1; i <= n; i++) c[0][i] = 0;//第0行設為0
for (i = 1; i <= m; i++)
for (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
{ c[i][j]=c[i][j-1];
b[i][j]=3;
}
}
}
這個方法是尋找子序列的最大長度。3個判斷條件的結果,簡單歸納為
[i-1,j-1] 【i-1,j】
【i,j-1】 (i,j)
假如,Xi=Yj,則是左上角b[i][j]=[i-1,j-1]+1。
如果,倆者不等,假如【i-1,j】大於【i,j-1】,則是取【上】一個值b[i][j]=【i-1,j】。
假如【i-1,j】小於【i,j-1】,則是取【左】邊一個值b[i][j]=【i,j-1】。
即使倆個【】誰大,b[i][j]就等於誰的值。
當倆個序列中有第一個值相等時,就將該座標記為1,並將這個“1”在該行傳遞下去,直到結束該行。
在下一行中也將把上一行的“1”繼承,如果在此行中有第二個值相同時,就執行b[i][j]=[i-1,j-1]+1,
就是將本來的“1”+1,變成了2,此時的最大長度就變成了2,以此類推,直至倆個序列都找完,最後的c[i][j]就是所需要的長度。
void LCS(int i,int j, char x[] ,int b[][])
{
if (i ==0 || j==0) return;
if (b[i][j]== 1) //輸出該序號
{
LCS(i-1,j-1,x,b);//【1】
System.out.print(x[i]+" ");
}
else if (b[i][j]== 2) //向上找
LCS(i-1,j,x,b);
else //b[i][j]=3,向左找
LCS(i,j-1,x,b);
}
該方法是輸出子序列,是從大到小尋找。但不會倒序輸出,因為當滿足第一個if條件時,此時已經找到最後一個元素,
但首先會執行【1】,即已經去尋找前一個元素,以此類推,直到找到子序列的第一個元素,接著從頭到尾輸出,完成子序列。
原始碼:
import java.util.*;
public class S3_1 {
static char x[]=new char[100];
static char y[]=new char[100];
static int c[][]=new int[100][100];
static int b[][]=new int[100][100];
int t=0;
public static void main(String[] args) {
S3_1 s=new S3_1();
Scanner sc=new Scanner(System.in);
System.out.println("輸入倆個序列");
System.out.println("輸入序列1、2的長度:");
int m=sc.nextInt();
int n=sc.nextInt();
System.out.println("1:");
for(int i=1;i<=m;i++) {
x[i]=sc.next().charAt(0);
}
System.out.println("2:");
for(int i=1;i<=n;i++) {
y[i]=sc.next().charAt(0);
}
s.LCSLength(x, y, m, n, c, b);
System.out.println("最長公共子序列為:");
s.LCS(m, n, x, b);
}
void LCSLength (char x[] ,char y[], int m, int n, int c[][], int b[][])
{
int i,j;
for (i = 1; i <= m; i++) c[i][0] = 0;//第0列設為0
for (i = 1; i <= n; i++) c[0][i] = 0;//第0行設為0
for (i = 1; i <= m; i++)
for (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
{ c[i][j]=c[i][j-1];
b[i][j]=3;
}
}
}
void LCS(int i,int j, char x[] ,int b[][])
{
if (i ==0 || j==0) return;
if (b[i][j]== 1) //輸出該序號
{
LCS(i-1,j-1,x,b);//【1】
System.out.print(x[i]+" ");
}
else if (b[i][j]== 2) //向上找
LCS(i-1,j,x,b);
else //b[i][j]=3,向左找
LCS(i,j-1,x,b);
}
}
相關文章
- 最長公共子序列
- java 實現 最長公共子序列Java
- 最長公共子序列求方案數
- 線性dp:最長公共子序列
- 動態規劃-最長公共子序列動態規劃
- 動態規劃——最長公共子序列動態規劃
- 演算法題:最長公共子序列演算法
- 力扣1143. 最長公共子序列 動態規劃之最長公共子序列力扣動態規劃
- 動態規劃(最長公共子序列LCS)動態規劃
- LCS 演算法:Javascript 最長公共子序列演算法JavaScript
- 最長公共子序列的程式碼實現
- 【LeetCode動態規劃#14】子序列系列題(最長遞增子序列、最長連續遞增序列、最長重複子陣列、最長公共子序列)LeetCode動態規劃陣列
- 最長公共子序列,遞迴簡單程式碼遞迴
- [演算法筆記]動態規劃之最長公共子串和最長公共子序列演算法筆記動態規劃
- 最長公共子序列問題—動態規劃sdut動態規劃
- LeetCode 1143.最長公共子序列LeetCode
- [題解]P1439 【模板】最長公共子序列
- 字串篇(python)—兩個字串的最長公共子序列字串Python
- 動態規劃經典問題----最長公共子序列動態規劃
- 51nod-基因匹配+luogu-【模板】最長公共子序列
- lCS(最長公共子串)
- 最長上升子序列
- 經典演算法題每日演練——最長公共子序列演算法
- 詳解動態規劃最長公共子序列--JavaScript實現動態規劃JavaScript
- 最長公共子序列&迴文字串 nyoj動態規劃字串動態規劃
- [譯] Swift 演算法學院 - 最長公共子序列演算法Swift演算法
- [Java] 藍橋杯ADV-202 演算法提高 最長公共子序列Java演算法
- 線性dp:最長公共子串
- 動態規劃之最長公共子序列求解動態規劃
- 兩個字串的最長公共子串字串
- 以最長公共子序列問題理解動態規劃演算法(DP)動態規劃演算法
- “最長公共字串子序列”問題的動態規劃法演算法字串動態規劃演算法
- 線性dp:最長上升子序列
- 領釦LintCode演算法問題答案-77. 最長公共子序列演算法
- 淺談最長公共子序列引發的經典動態規劃問題動態規劃
- 最長公共子序列與最小編輯距離-你有更快的演算法麼?演算法
- 動態規劃:最長上升子序列動態規劃
- 最長上升子序列動態規劃動態規劃