字符串最长公共子序列问题

找两个字符串的最长公共子序列,最长公共子序列并不要求连续。

代码如下:

package string;

import java.util.ArrayList;
import java.util.List;

/**
 * 字符串的最长公共子序列问题
 * @author Administrator
 *
 */
public class LCSequence {

    /**
     * 求最长公共子序列长度
     * @param s1
     * @param s2
     * @return
     */
    public int getMaxLCSLen(String s1, String s2){
        int maxLen = 0;
        if(s1 == null || s2 == null){
            return maxLen;
        }
        int m = s1.length();
        int n = s2.length();
        // a[i][j]记录s1[0~i-1]与s2[0~j-1]的最长公共子序列长度
        int[][] a = new int[m+1][n+1];
        for(int i = 1; i <= m; i++){
            for(int j = 1; j <= n; j++){
                if(s1.charAt(i-1) == s2.charAt(j-1)){
                    a[i][j] = Math.max(a[i][j-1], a[i-1][j-1] + 1);
                    a[i][j] = Math.max(a[i][j], a[i-1][j]);
                }else{
                    a[i][j] = Math.max(a[i][j-1], a[i-1][j]);
                }
                maxLen = Math.max(maxLen, a[i][j]);
            }
        }
        return maxLen;
    }

    /**
     * 求最长公共子序列
     * @param s1
     * @param s2
     * @return
     */
    public List<String> getMaxLCS(String s1, String s2){
        int maxLen = 0;
        List<String> res = new ArrayList<String>();
        if(s1 == null || s2 == null){
            return res;
        }
        int m = s1.length();
        int n = s2.length();
        // a[i][j]记录s1[0~i-1]与s2[0~j-1]的最长公共子序列长度
        int[][] a = new int[m+1][n+1];
        for(int i = 1; i <= m; i++){
            for(int j = 1; j <= n; j++){
                if(s1.charAt(i-1) == s2.charAt(j-1)){
                    a[i][j] = Math.max(a[i][j-1], a[i-1][j-1] + 1);
                    a[i][j] = Math.max(a[i][j], a[i-1][j]);
                }else{
                    a[i][j] = Math.max(a[i][j-1], a[i-1][j]);
                }
                if(a[i][j] == maxLen){
                    String s = s1.substring(i-a[i][j], i);
                    if(!res.contains(s)){
                        res.add(s);
                    }
                } else if(a[i][j] > maxLen){
                    maxLen = a[i][j];
                    res = new ArrayList<String>();
                    res.add(s1.substring(i-a[i][j], i));
                }
            }
        }
        return res;
    }

    public static void main(String[] args) {
        LCSequence lcs = new LCSequence();
        String s1 = "a1b2c3";
        String s2 = "1a1wbz2c123a1b2c123";
        System.out.println(lcs.getMaxLCSLen(s1, s2));
        System.out.println(lcs.getMaxLCS(s1, s2));
    }

}
时间: 2024-08-13 16:40:14

字符串最长公共子序列问题的相关文章

实习生面试--算法题之字符串最长公共子序列长度

题目:求两字符串的最长公共子序列的长度. 题外话:最长公共子串,子序列问题是被充分讨论的问题,网上一搜一大把,请bing之. 本题只要求求最长公共子序列的长度,而不需要记录最长的公共子序列,给予了我们便利,请参考代码: 1 int max(int a, int b) 2 { 3 return a > b ? a : b; 4 } 5 6 int lcs(char* str1, char* str2) 7 { 8 if (str1 == nullptr || str2 == nullptr) 9

51Nod 1092 回文字符串 | 最长公共子序列变形

求字符串和其逆的最长公共子序列,需要添加的字符数就为长度-最长公共子序列长 #include "stdio.h" #include "string.h" #define maxn 1005 char s[maxn],s1[maxn]; int dp[maxn][maxn]; int main() { int n=0,i,j,len; scanf("%s",s); len=strlen(s); strcpy(s1,s); strrev(s1); f

C++求解汉字字符串的最长公共子序列 动态规划

    近期,我在网上看了一些动态规划求字符串最长公共子序列的代码.可是无一例外都是处理英文字符串,当处理汉字字符串时.常常会出现乱码或者不对的情况. 我对代码进行了改动.使用wchar_t类型存储字符串,可以正确的处理英文字符串和汉字字符串的最长公共子序列. 代码例如以下: #include "stdafx.h" #include <iostream> #define N 1000 using namespace std; //str1存储字符串1,str2存储字符串2

POJ 1458 - Common Subsequence(最长公共子序列) 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:http://poj.org/problem?id=1458 题目大意: 有若干组数据,每组给出两个字符串(中间用任意数量的空格间隔),输出这两个字符串最长公共子序列的长度.每次输出后换行. 分析: 动态规划求LCS,f[i][j]表示第一个字符串匹配到第i位,第二个字符串匹配到第j位时最长公共子序列的长度. 转移方程:当a[i] = b[i]时,f[i][j] = f[i-1][j-1]+1,其他情况时f[i][j

最长递增子序列 &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),其实还有更好的方

求解两个字符串的最长公共子序列

一,问题描述 给定两个字符串,求解这两个字符串的最长公共子序列(Longest Common Sequence).比如字符串1:BDCABA:字符串2:ABCBDAB 则这两个字符串的最长公共子序列长度为4,最长公共子序列是:BCBA 二,算法求解 这是一个动态规划的题目.对于可用动态规划求解的问题,一般有两个特征:①最优子结构:②重叠子问题 ①最优子结构 设 X=(x1,x2,.....xn) 和 Y={y1,y2,.....ym} 是两个序列,将 X 和 Y 的最长公共子序列记为LCS(X,

(字符串)最长公共子序列(Longest-Common-Subsequence,LCS)

问题: 最长公共子序列就是寻找两个给定序列的子序列,该子序列在两个序列中以相同的顺序出现,但是不必要是连续的. 例如序列X=ABCBDAB,Y=BDCABA.序列BCA是X和Y的一个公共子序列,但是不是X和Y的最长公共子序列,子序列BCBA是X和Y的一个LCS,序列BDAB也是. 思路: 1.最简单的方法就是暴力枚举. 先列举X所有的子序列,然后检查是否为Y的子序列,并记录最长的子序列.当该方法复杂度太高,假设X的长度为m,则X的子序列个数为2^m,指数级的复杂度是不实际的. 2.动态规划思想.

回文字符串(南阳oj37)(最长公共子序列问题)

回文字符串 时间限制:3000 ms  |  内存限制:65535 KB 难度:4 描述 所谓回文字符串,就是一个字符串,从左到右读和从右到左读是完全一样的,比如"aba".当然,我们给你的问题不会再简单到判断一个字符串是不是回文字符串.现在要求你,给你一个字符串,可在任意位置添加字符,最少再添加几个字符,可以使这个字符串成为回文字符串. 输入 第一行给出整数N(0<N<100) 接下来的N行,每行一个字符串,每个字符串长度不超过1000. 输出 每行输出所需添加的最少字符

求三个字符串的最长公共子序列LCS(A,B,C)

LCS(A,B,C)!=LCS(A,LCS(B,C)) 反例: abcd abcde abced LCS(B,C)求出来可能是abce或者abcd dp[i][j][k]表示A[0...i],B[0...j],C[0...k]的LCS 转移方程: if (a[i]==b[j]&&b[j]==c[k]) dp[i][j][k]=dp[i-1][j-1][k-1]+1; else dp[i][j][k]=max(max(dp[i][j][k], dp[i-1][j][k]), max(dp[i