zoukankan      html  css  js  c++  java
  • 最长公共子序列问题解析

    问题解读


    最长公共子序列问题,就是找出两个字符串中,存在的最长的子序列

    什么是子序列呢?
    子序列不同于公共子串,子串是每个字符连续的,子序列不一定要连续,见下例 [example]

    [example]: 比如 mStringA = "abc11google11111111", mStringB = "1111111141615" 这两个字符串
    那么,mStringA 和 mStringB 的最长公共子序列就是 1111111111


    如何求解

    我们对于问题进行白话讲解,假如现在有两个字符串,并且有两个指针,这每个指针,各自指向这两个字符串,我们把这两个指针设置为 i 和 j,即,i 指向 mStringA 的某个字符,j 指向 mStringB 的某个字符,那么,此时的状态方程为 f(i, j),表示 i 指向 mStringA 的某个字符和 j 指向 mStringB 的某个字符的情况

    • 当两个指针指向的字符相等时,那么代表这是一个成功的状态,此时,状态记为f(i + 1, j + 1) + 1,表示 i 和 j 两个指针可以同时向右方移动
    • 当两个指针指向的字符不相等的试试,那么代表这是一个待完成的状态,此时,状态记为 f(i + 1, j)f(i, j + 1)

    Talk is cheap, show me code ~~~

    package com.company;
    
    import org.junit.Test;
    
    public class LongestCommonSequence {
        // 用来存储匹配过程中存取的记录
        public StringBuilder sb = new StringBuilder();
        /* 
        * 获得最长公共子序列的方法
        * 传入两个参数,即为需要处理的字符串
        * 核心实现方法在 longestCommonSequence(...)
        */
        public String getLongestCommonSequence(String mStringA, String mStringB) {
            // 1. 拿到最长公共子序列的长度
            int strLength = longestCommonSequence(0, mStringA, 0, mStringB);
            // 2. 将 StringBuilder 转为 String 类
            String mString = new String(sb);
            // 3. 对记录进行裁剪,最后的 strLength 个字符,是最终的结果
            return mString.substring(
                    strLength - longestCommonSequence(0, mStringA, 0, mStringB),
                    strLength);
        }
    
        // 最长公共子序列的实现方法
        public int longestCommonSequence(int i, String mStringA, int j, String mStringB) {
            // 1. 边界条件判断,当指针到头的时候,返回 0
            if (i == mStringA.length() || j == mStringB.length()) {
                return 0;
            }
            // 2. 当两个指针指向的字符相等的时候,这是状态方程为:f(i + 1, j + 1) + 1
            if (mStringA.charAt(i) == mStringB.charAt(j)) {
                sb.append(mStringA.charAt(i));
                return longestCommonSequence(i + 1, mStringA, j + 1, mStringB) + 1;
            } else { // 3. 当两个指针指向的字符不相等的时候,这是状态方程为:f(i + 1, j) 或者 f(i, j + 1)
                return Math.max(longestCommonSequence(i + 1, mStringA, j, mStringB),
                        longestCommonSequence(i, mStringA, j + 1, mStringB));
            }
        }
        
        // 测试方法
        @Test
        public void test() {
            // 1111111111
            System.out.println(
                    getLongestCommonSequence("abc11google11111111",
                            "1111111141615")
            );
        }
    }
    
    

    掘金地址

  • 相关阅读:
    洛谷P4587 [FJOI2016]神秘数(主席树)
    洛谷P4609 [FJOI2016]建筑师(第一类斯特林数+组合数)
    Bzoj4016/洛谷P2993 [FJOI2014] 最短路径树问题(最短路径问题+长链剖分/点分治)
    Bzoj1486/洛谷P3199 最小圈(0/1分数规划+spfa)/(动态规划+结论)
    Bzoj4753/洛谷P4432 [JSOI2016]最佳团体(0/1分数规划+树形DP)
    Bzoj3197/洛谷3296 [SDOI2013]刺客信条assassin(树的重心+树Hash+树形DP+KM)
    关于二分图的完美匹配问题
    Bzoj3837 [Pa2013]Filary(随机化)
    Bzoj3566/洛谷P4284 [SHOI2014]概率充电器(概率dp)
    杜教筛学习笔记
  • 原文地址:https://www.cnblogs.com/newcaoguo/p/9756923.html
Copyright © 2011-2022 走看看