繁体   English   中英

找到2个字符串的最长公共子序列?

[英]Find longest common subsequence of 2 String?

我正在学习最长的公共子序列,使用这些算法:

成本表算法


在此处输入图像描述

公开课 LCS {

static int[][] E;
static int[][] S;
static int D;
static int T;
static int L;
public static void LCS_cost(String X,String Y)
{       
    int m = X.length();
    int n = Y.length();
    E = new int[m][n];
    S = new int[m][n];
    for(int i=0;i<m;i++){
        E[i][0] = 0;
    }
    for(int j=0;j<n;j++){
        E[0][j] = 0;
    }
    for(int i=1;i<m+1;i++){
        for(int j=1;j<n+1;j++){
            if(X.charAt(i) == Y.charAt(j)){
                E[i][j] = E[i-1][j-1]+1;
                D =  E[i-1][j-1]+1;
                S[i][j] = D;//Diagonal Direction    
            }
            else if (E[i-1][j]>=E[i][j-1]){
                    E[i][j] = E[i-1][j];
                    T = E[i-1][j];
                    S[i][j] = T;//TOP
            }
            else
                    E[i][j] = E[i][j-1];
                    L = E[i][j-1];
                    S[i][j] = L;//Left
        }
    }

}

public static void Backtrack(int[][] S,String X,String Y){
int row = X.length();
int col = Y.length();   

while (row > 0 || col > 0){
    if (S[row][col] == D){
        System.out.print(X.charAt(row));
        row--;
        col--;
    }
    else if (S[row][col] == T){
        row--;
    }
    else
        col--;
}
}
public static void main(String[] args) {
    new  LCS();
    LCS_cost("SCHOOL","SPOOL");
    Backtrack(S,"SCHOOL", "SPOOL");
    }
}

但是程序返回一个 ErrorCharAt(Unknow Source) 并且没有做任何事情。

我正在努力改变

for(int i=1;i<m+1;i++){
        for(int j=1;j<n+1;j++){

for(int i=1;i<m;i++){
        for(int j=1;j<n;j++){

结果是这一行 IndexOutofBoud

if (S[row][col] == D){
    ....
    }

此外,如果我将int ij更改为 0,则下面的 E 将是索引 -1 和错误

for(int i=0;i<m;i++){
        for(int j=0;j<n;j++){
            if(X.charAt(i) == Y.charAt(j)){
                E[i][j] = E[i-1][i-1]+1;
                ......
            }

我现在迷路了。有人能帮帮我吗?

我会使用字符串而不是处理单个字符来解决这个问题:

String findLCS(String str1, String str2) {
    int longest = 0;
    String longestSubstring = "";

    for (int i=0; i < str1.length(); ++i) {
        for (int j=i+1; j <= str1.length(); ++j) {
            String substring = str1.substring(i, j);
            if (str2.contains(substring) && substring.length() > longest) {
                longest = substring.length();
                longestSubstring = substring;
            }
        }
    }

    return longestSubstring;
}

如您所见,使用String.contains()比看起来更强大。

如果

 int m = X.length();

然后

for(int i=1;i<m+1;i++){
   ...
   if(X.charAt(i) ....

将抛出错误,因为 Java 数组是基于零的

还有如果

int row = X.length();
int col = Y.length(); 

if (S[row][col] == D){

会抛出错误

另外,使用 String.equals 比较字符串而不是==

导入 java.util.Scanner; 类主要{

public static void main(String[] args)
{


Scanner sc=new Scanner(System.in);




    Sub s=new Sub();

    int t=Integer.parseInt(sc.nextLine());

    for(int i=1;i<=t;i++)
    {




    String a=sc.next();
    String b=sc.next();

    System.out.println("Case "+i+": "+s.subString(a, b));


}

}

} 类子 {

   public static int subString (String a,String b)
   {

       int max=0;
       int m=a.length();
       int n=b.length();

       int dp[][]=new int [m][n];

       for(int i=0;i<m;i++)
       {

           for(int j=0;j<n;j++)
           {

               if(a.charAt(i)==b.charAt(j))

               {
                   if(i==0||j==0)
                   {
                       dp[i][j]=1;
                   }
                   else 
                       dp[i][j]=dp[i-1][j-1]+1;
               }

               if(max<dp[i][j])

                   max=dp[i][j];
           }


       }


       return max;

   }

}

您正在使用矩阵方法,我们,

  • 如果第 [i] 个字符和第 [j] 个字符匹配 - 沿对角线 [i-1][j-1] 值移动前一个并为 lcs 长度加 1
  • 如果第 [i] 个字符和第 [j] 个字符不匹配 - 然后为 lcs 取 {left [i][j-1] 或 right [i-1][j] 的最大值。

我个人觉得这种方法更像脚本,动态规划和记忆的本质在它背后脱落。 当我们更多地依赖脚本方法而不是 DP 和备忘录的纯逻辑时——我们更容易出错或可能在两者之间迷失……

我没有使用矩阵方法,而是使用动态规划和记忆来将 LCS 演示为 -

package com.company.dynamicProgramming;

import java.util.HashMap;
import java.util.Map;

public class LongestCommonSubsequnce {


    public static void main(String ...args){

        String s1 = "SCHOOL";
        String s2 = "SPOOL";
        System.out.println(new StringBuilder(findLcs(s1, s2, new HashMap<>())).reverse());
    }



    static String findLcs(String s1, String s2, Map<String, String> memo){

        //check if lcs is already processed in memo for s1 & s2
        String lcs = memo.get(s1+"-"+s2);
        if(lcs != null){
            return lcs;
        }


        if (s1.substring(s1.length()-1).equals(s2.substring(s2.length()-1))){
            lcs = s1.substring(s1.length()-1);
            if(s1.length()>1 && s2.length()>1){
                lcs = lcs + findLcs(s1.substring(0, s1.length()-1), s2.substring(0, s2.length()-1), memo);
                memo.put(s1.substring(0, s1.length()-1)+ "-" + s2.substring(0, s2.length()-1), lcs);
            }
            else {
                memo.put(s1+"-"+s1, lcs);
            }
            return lcs;

        }else {

            String lcs1="";
            String lcs2="";

            if(s1.length()>1 && s2.length()>1){
                lcs1 = findLcs(s1.substring(0, s1.length()-1), s2, memo);
                memo.put(s1.substring(0, s1.length()-1)+"-"+s2, lcs1);
                lcs2 = findLcs(s1,s2.substring(0, s2.length()-1),memo);
                memo.put(s1 +"-"+s2.substring(0, s2.length()-1), lcs2);
            }
            else if(s1.length()>1){
                lcs1 = findLcs(s1.substring(0, s1.length()-1), s2, memo);
                memo.put(s1.substring(0, s1.length()-1)+"-"+s2, lcs1);
            }
            else if(s2.length()>1){
                lcs2 = findLcs(s1,s2.substring(0, s2.length()-1),memo);
                memo.put(s1 +"-"+s2.substring(0, s2.length()-1), lcs2);
            }else {
                memo.put(s1+"-"+s2,"");
            }

            if(lcs1.length() >= lcs2.length()){
                return lcs1;
            }else {
                return lcs2;
            }
        }
    }
}

运行这段代码,结果是——

SOOL

Process finished with exit code 0

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM