最长公共子序列与最长公共字串

显然最长公共子序列不一定需要连续的,只要字符的顺序严格递增即可。最长公共字串需要字符连续

子序列代码:

package test;

import java.util.*;
/*
 * 本题是求最长公共子序列,子序列未必连续,只需要严格递增即可
 * 如  abcdeeeeeeeee和atttbggcd 最长公共子序列为abcd 长度为4
 *
 * */
public class Main4{
    public static void main(String... args){
        try(Scanner in = new Scanner(System.in)){
            while(in.hasNext()){

                String s1 = in.nextLine();
                String s2 = in.nextLine();
                String min1 = s1.length() < s2.length()? s1 : s2;
                String max1 = s1.equals(min1) ? s2 : s1;
                 //dp[i][j]表示i串和j串的最长公共字串
                char[] min = min1.toCharArray();
                char[] max = max1.toCharArray();
                int[][] dp = new int[max.length+1][max.length+1];
                for(int i = 1; i < min.length + 1;i++) {
                    for(int j = 1; j < max.length + 1;j++) {
                        if(min[i-1] == max[j-1]) {
                            dp[i][j] = dp[i-1][j-1] + 1;
                        }else {
                            dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
                        }
                    }
                }

                for(int i = 0; i < min.length + 1; i++) {
                    for(int j = 0; j < max.length + 1;j++) {
                        if(j == max.length)
                            System.out.println(dp[i][j]);
                        else System.out.print(dp[i][j] + "  ");
                    }
                }
                System.out.println("++++++++++++++++++++");
                int flag = 0;
                for(int i = 0; i < min.length + 1;i++) {
                    for(int j = 0; j < max.length + 1; j++) {
                        if(dp[i][j] == flag + 1) {
                            System.out.print(max[j-1]);
                            flag = dp[i][j];
                        }
                    }
                }
            }
        }
    }
}

最长公共字串代码

package test;

import java.util.*;
public class Main2{
    public static void main(String... args){
        try(Scanner in = new Scanner(System.in)){
            while(in.hasNext()){

                String s1 = in.nextLine();
                String s2 = in.nextLine();
                String min1 = s1.length() < s2.length()? s1 : s2;
                String max1 = s1.equals(min1) ? s2 : s1;
                 //dp[i][j]表示i串和j串的最长公共字串
                char[] min = min1.toCharArray();
                char[] max = max1.toCharArray();
                int[][] dp = new int[max.length+1][max.length+1];
                for(int i = 1; i < min.length + 1;i++) {
                    for(int j = 1; j < max.length + 1;j++) {
                        if(min[i-1] == max[j-1]) {
                            dp[i][j] = dp[i-1][j-1] + 1;
                        }
                    }
                }

                for(int i = 0; i < min.length + 1; i++) {
                    for(int j = 0; j < max.length + 1;j++) {
                        if(j == max.length)
                            System.out.println(dp[i][j]);
                        else System.out.print(dp[i][j] + "  ");
                    }
                }
                System.out.println("++++++++++++++++++++");
                int flag = 0;
                int MAX = 0;
                int end = 0;

                for(int i = 1; i < min.length + 1;i++) {
                    for(int j = 1; j < max.length + 1; j++) {
                        if(dp[i][j] > MAX) {
                            MAX = dp[i][j];
                            end = j;
                        }
                    }
                }
                System.out.println("MAX为:"+ MAX);
                System.out.println("end为:"+ end);
                for(int i = end - MAX ; i < end; i++) {
                    if(i == end - 1) System.out.println(max[i]);
                    else System.out.print(max[i]);
                }
            }
        }
    }
}

仔细比对两处代码可知,公共子序列需要将每一次循环中记录子序列的结果,dp的值一直更新(虽然值有可能不变)。而公共字串只有当字符连续的时候,dp值才会发生更新。

公共子序列在输出结果时,我们可以先把状态矩阵打印出来,观察矩阵可知,当每组数据第一次发生变化,就是子序列的值。比如

当然,也可以纵向理解,则打印出min的第一次变化处的值即可。

原文地址:https://www.cnblogs.com/theWinter/p/11260340.html

时间: 2024-10-10 23:17:19

最长公共子序列与最长公共字串的相关文章

最长递增子序列 &amp;&amp; 最大子序列、最长递增子序列、最长公共子串、最长公共子序列、字符串编辑距离

http://www.cppblog.com/mysileng/archive/2012/11/30/195841.html 最长递增子序列问题:在一列数中寻找一些数,这些数满足:任意两个数a[i]和a[j],若i<j,必有a[i]<a[j],这样最长的子序列称为最长递增子序列. 设dp[i]表示以i为结尾的最长递增子序列的长度,则状态转移方程为: dp[i] = max{dp[j]+1}, 1<=j<i,a[j]<a[i]. 这样简单的复杂度为O(n^2),其实还有更好的方

最长公共子序列和最长递增子序列

1.最长公共子序列:(x和y是两个数组的长度) f(x,y) = 0                               if(x==0 || y==0) f(x-1,y-1)+1               if(A[x-1]==B[y-1]) max{f(x-1,y), f(x,y-1)} if(A[x-1]!=B[y-1]) 2.最长递增子序列 (1) 最长公共子序列法:排序后与原数组的最长公共子序列. (2) 动态规划法:(时间复杂度O(N^2)) 设长度为N的数组为{a0,a1

O(n log n)求最长上升子序列与最长不下降子序列

考虑dp(i)表示新上升子序列第i位数值的最小值.由于dp数组是单调的,所以对于每一个数,我们可以二分出它在dp数组中的位置,然后更新就可以了,最终的答案就是dp数组中第一个出现正无穷的位置. 代码非常简单: for(int i=0;i<n;i++)dp[i]=oo; for(int i=0;i<n;i++)*lower_bound(dp,dp+n,A[i])=A[i]; printf("%d\n",(lower_bound(dp,dp+n,oo)-dp)); 如果是最长不

[Data Structure] LCSs——最长公共子序列和最长公共子串

什么是 LCSs? 什么是 LCSs? 好多博友看到这几个字母可能比较困惑,因为这是我自己对两个常见问题的统称,它们分别为最长公共子序列问题(Longest-Common-Subsequence)和最长公共子串(Longest-Common-Substring)问题.这两个问题非常的相似,所以bbs.chinaacc.com/forum-2-3/topic-5611515.html bbs.chinaacc.com/forum-2-3/topic-5611514.html bbs.chinaac

最长递归子序列、最长公共字串、最长公共子序列、编辑距离

[TOC]   ### 最长递归子序列 #### 题目 给定数组arr,返回arr中的最长递增子序列,如`arr=[2,1,5,3,6,4,8,9,7]`,返回的最长递增子序列为`[1,3,4,8,9]` #### 题解思路 先用DP来求解子序列递增的最大长度,如arr的长度序列为`dp=[1,1,2,2,3,3,4,5,4]`,然后对这个长度序列dp从右到左遍历,得到最长递增子序列. 1. 求解长度序列,令dp[i]表示在以arr[i]这个数结尾的情况下,arr[0...i]中的最大递增子序列

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

最长公共子序列: 例如:abcfbc abfcb                答案是:4: 最长公共子串  :答案是: 2: 代码: 最长公共子序列: #include<cstdio> #include<cstring> #define max(x,y) (x>y?x:y) int len1,len2; int dp[1010][1010]; int bj[1010][1010]; char ch1[1010],ch2[1010]; void LCS() //lcs最长公共

最长公共子序列、最长公共子串

最长公共子序列: class Solution { public: int findLength(vector<int>& A, vector<int>& B) { int len1 = A.size(); int len2 = B.size(); if(len1 == 0 || len2 == 0) return 0; vector<vector<int>> result(len1+1,vector<int>(len2+1));

最长公共子序列 与 最长公共连续子串

最长公共子序列 //最长公共子序列(个数) #include<iostream> using namespace std; int c[100][100]={0}; int len1,len2; int gcd(string a,string b){ len1=a.length(); len2=b.length(); int tmp=-1; for(int i=0;i<len1;i++) { for(int j=0;j<len2;j++){ if(a[i]==a[j]) c[i][

最长上升子序列问题/最长公共子序列问题

这个时候边界不是很好确定,所以可以使用记忆化搜索比较容易一点 需要注意的一点是: 更新状态的时候,一定要使用dp(x),而不是d[x] #include<cstdio> #include<algorithm> using namespace std; int A[] = {0,1,5,2,6,8,7}; int B[] = {0,2,3,5,6,9,8,4}; const int maxn = 10; int d[maxn][maxn];//i,j代表A1~i与B1~j的最长公共子