最长公共子序列
给你两个字符串,找出他们的公共子序列
代码
import java.util.Scanner;
// xzyzzyx
// zxyyzxz
public class Test {
public static void main(String[] args)
{
String str1 ;
String str2 ;
int n ,m ;
Scanner sc = new Scanner(System.in);
System.out.println("输入第一个字符串:");
str1 = sc.nextLine();
System.out.println("输入第二个字符串:");
str2 = sc.nextLine();
n=str1.length();
m=str2.length();
int[][] z=new int[n+1][m+1];//+1是因为第一行第一列初始化
int[][] path=new int[n+1][m+1];//递归路径
findLCS(str1,n,str2,m,path,z);
System.out.println("对照数组z为:");
for(int i=0;i<n+1;i++)
{
for(int j=0;j<m+1;j++)
{
System.out.print(z[i][j]+"\t");
}
System.out.println();
}
System.out.println("递归路径path为:");
for(int i=0;i<n+1;i++)
{
for(int j=0;j<m+1;j++)
{
System.out.print(path[i][j]+"\t");
}
System.out.println();
}
System.out.println("LCS的长度为:"+z[n][m]);
System.out.println("LCS为:");
printfLCS(path,str1,n,m);
}
public static void findLCS(String x, int n, String y, int m,int[][] path,int[][] z)
{
for(int i=0;i<n;i++)
z[i][0]=0;//第一列初始化为0
for(int j=0;j<m;j++)
z[0][j]=0;//第一行初始化为0
for(int i=1;i<n+1;i++)
{
for(int j=1;j<m+1;j++)
{
if(x.charAt(i-1)==y.charAt(j-1))
z[i][j]=z[i-1][j-1]+1;
else if(z[i-1][j]>=z[i][j-1])
{
z[i][j]=z[i-1][j];
path[i][j]=1;
}
else
{
z[i][j]=z[i][j-1];
path[i][j]=-1;
}
}
}
}
public static void printfLCS(int[][] path,String x,int n,int m)
{
if(n ==0|| m ==0)
return;
if(path[n][m]==0)
{
printfLCS(path,x,n-1,m-1);
System.out.print(x.charAt(n -1));
}
else if(path[n][m]==1)
{
printfLCS(path,x,n-1,m);
}
else
printfLCS(path,x,n,m-1);
}
}
整体思路:
初始化一个二位对照数组z,通过两个for循环逐个比较每个字符,然后将比较过程中的情况记录在二维对照数组z,同时在比较过程中,记录path数组,该数组决定搜索方向,自底向上逐层递归,得到结果