美文网首页
求最长公共子序列

求最长公共子序列

作者: Stroman | 来源:发表于2018-03-11 15:21 被阅读10次

问题

给出两个字符串,求出它们之中相对顺序相同,字符相同的最长的公共子序列。

用法

package com.company;

public class Main {

    public static void main(String[] args) {
    // write your code here
        String string0 = "abcicba";
        String string1 = "abdkscab";
        System.out.println(Solution.findLongestSubsequence(string0,string1));
    }
}

输出

解集:
1 1 1 1 1 1 1 1 
1 2 2 2 2 2 2 2 
1 2 2 2 2 3 3 3 
1 2 2 2 2 3 3 3 
1 2 2 2 2 3 3 3 
1 2 2 2 2 3 3 4 
1 2 2 2 2 3 4 4 
最长公共子序列长度为:4
倒序输出最长子序列:ab<>c<>a

Process finished with exit code 0

代码实现

package com.company;

public class Solution {
    /**
     * 查找两个字符串的最长公共子序列。
     * 所谓最长公共子序列,需要满足两个条件。
     * 1、它包含的字符相同。
     * 2、相对顺序相同。
     * 最长公共子序列并不是最长公共子串
     * 二者的区别很大。
     * 很简单如果矩阵对应的两个字符不相等,该单元格的值就等于它上面的和左边的较大的单元格的值。
     * 如果相等,就等于左上角单元格的值+1。
     * 本问题需要输出那个子序列,这个有点麻烦,从解集可以看出来
     * 不一定相等就是最长公共子序列的开始。
     * 所以用单链表的回溯法可以打印出最长公共子序列。
     * 把其中重复的结点合并作为间隔符<>来显示
     * @param string0
     * @param string1
     * @return
     */
    static public String findLongestSubsequence(String string0,String string1) {
        if (string0.length() == 0 || string1.length() == 0)return "";
        SingleLinker[][] answerArray = new SingleLinker[string0.length()][string1.length()];
        for (int counter = 0;counter < string0.length();counter++) {
            for (int counter0 = 0;counter0 < string1.length();counter0++) {
                answerArray[counter][counter0] = new SingleLinker(counter,counter0);
                if (string0.charAt(counter) == string1.charAt(counter0)) {
                    if (counter - 1 >= 0 && counter0 - 1 >= 0) {
                        answerArray[counter][counter0].setEqualCounter(answerArray[counter - 1][counter0 - 1].getEqualCounter() + 1);
                        answerArray[counter][counter0].prePointer = answerArray[counter - 1][counter0 - 1];
                    }
                    else answerArray[counter][counter0].setEqualCounter(1);
                }
                else {
                    if (counter - 1 >= 0 && counter0 - 1 < 0) {
                        answerArray[counter][counter0].setEqualCounter(answerArray[counter - 1][counter0].getEqualCounter());
                        answerArray[counter][counter0].prePointer = answerArray[counter - 1][counter0];
                    }
                    else if (counter - 1 < 0 && counter0 - 1 >= 0) {
                        answerArray[counter][counter0].setEqualCounter(answerArray[counter][counter0 - 1].getEqualCounter());
                        answerArray[counter][counter0].prePointer = answerArray[counter][counter0 - 1];
                    }
                    else if (counter - 1 < 0 && counter0 - 1 < 0)
                        answerArray[counter][counter0].setEqualCounter(0);
                    else {
                        if (answerArray[counter - 1][counter0].getEqualCounter() > answerArray[counter][counter0 - 1].getEqualCounter()) {
                            answerArray[counter][counter0].setEqualCounter(answerArray[counter - 1][counter0].getEqualCounter());
                            answerArray[counter][counter0].prePointer = answerArray[counter - 1][counter0];
                        } else {
                            answerArray[counter][counter0].setEqualCounter(answerArray[counter][counter0 - 1].getEqualCounter());
                            answerArray[counter][counter0].prePointer = answerArray[counter][counter0 - 1];
                        }
                    }
                }
            }
        }
        System.out.println("解集:");
        for (int counter = 0;counter < string0.length();counter++) {
            for (int counter0 = 0;counter0 < string1.length();counter0++) {
                System.out.print(answerArray[counter][counter0].getEqualCounter() + " ");
            }
            System.out.println();
        }
        System.out.println("最长公共子序列长度为:" + answerArray[string0.length() - 1][string1.length() - 1].getEqualCounter());
        System.out.print("倒序输出最长子序列:");
        SingleLinker currentNode = answerArray[string0.length() - 1][string1.length() - 1];
        SingleLinker[] nodeStack = new SingleLinker[answerArray[string0.length() - 1][string1.length() - 1].getEqualCounter()];
        int nodeStackPointer = -1;
        while (currentNode != null && currentNode.getEqualCounter() > 0) {
            if (nodeStackPointer == -1 || nodeStack[nodeStackPointer].getEqualCounter() != currentNode.getEqualCounter())
                nodeStack[++nodeStackPointer] = currentNode;
            else {
                nodeStack[nodeStackPointer] = currentNode;
                nodeStack[nodeStackPointer].setHasDivider(true);
            }
            currentNode = currentNode.prePointer;
        }
        //逆转单链表
        StringBuilder longestSubsequence = new StringBuilder();
        while (nodeStackPointer > -1) {
            longestSubsequence.append(string0.charAt(nodeStack[nodeStackPointer].getX()));
            if (nodeStack[nodeStackPointer].isHasDivider() && nodeStackPointer != 0)longestSubsequence.append("<>");
            nodeStackPointer--;
        }
        return longestSubsequence.toString();
    }
}

package com.company;

public class SingleLinker {
    private int x = -1;
    private int y = -1;
    private int equalCounter = 0;
    private boolean hasDivider = false;
    public SingleLinker prePointer = null;

    public SingleLinker(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getEqualCounter() {
        return equalCounter;
    }

    public void setEqualCounter(int equalCounter) {
        this.equalCounter = equalCounter;
    }

    public boolean isHasDivider() {
        return hasDivider;
    }

    public void setHasDivider(boolean hasDivider) {
        this.hasDivider = hasDivider;
    }
}

相关文章

  • 动态规划

    1、求最长公共子序列 2、求最长公共子串 3、0-1背包问题 4、最短编辑距离

  • 公共子序列问题

    最长公共子序列 最长上升子序列 最长公共上升子序列

  • 每天一道算法题18

    【最长公共子序列,子串】给定两个字符串上str1 和 str2, 求两个字符的最长公共子序列和最长公共子串。 最长...

  • 最长公共子序列和最长公共子串

    最长公共子序列和最长公共子串区别 最长公共子串(Longest CommonSubstring)和最长公共子序列(...

  • Java算法:求两个字符串的最长公共子序列问题

    最长公共子序列问题: 给定两个字符串A、B,求A与B的最长公共子序列(子序列不要求是连续的)举例:字符串A: ab...

  • 2019-10-29

    求2个字符串的最长公共子序列和最长公共子字符串 一. 最长公共子序列 定义: 一个数列S,如果分别是两个或多个已知...

  • 最长公共子序列问题

    问题描述: 求两个字符序列的公共最长子序列。 最长公共子串 在回到子序列问题之前,先来了解一下子串的问题。例如,H...

  • 算法(04)动态规划

    零钱问题 背包问题 最长公共子序列 最长公共子串 最长上升子序列 最大连续子序列和

  • LCS问题

    LCS问题包括最长公共子序列和最长公共子串,其中,最长公共子串要求必须连续。 对于二者的求解方式 最长公共子序列:...

  • 子序列问题

    最长公共子序列 最长上升/下降/不升/不降子序列

网友评论

      本文标题:求最长公共子序列

      本文链接:https://www.haomeiwen.com/subject/fxlwfftx.html