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

来源:互联网 发布:0信誉淘宝店 编辑:程序博客网 时间:2024/05/18 02:14

求两个字符串的最长公共子序列和最长公共子串是两个问题。。
这次先解决子序列的问题。

从一个字符串S中移除零个或者多个字符得到的序列称为S的子序列。 例如”abcde”的子序列有”abe”,”“,”abcde”等。

定义LCS(S,T)为字符串S和字符串T最长公共子序列的长度,即一个最长的序列W既是S的子序列也是T的子序列的长度。

通用方法是通过动态规划求解。将问题本身化为相同规模的子问题求解。

比如要求字符串S和T的最大公共子序列,先比较字符串S的最后一个字符S[i]是否与字符串T的最后一个字符T[j]相同。如果相同,则问题化简为比较字符串S(0~i-1)与字符串T(0~j-1)的最大公共子序列。如果不相同,则分为两个子问题,比较字符串字符串S(0~i-1)与字符串T(0~j)的最大公共子序列,和比较字符串字符串S(0~i)与字符串T(0~j-1)的最大公共子序列,然后取两子问题中的大值作为原问题的结果。
下图为借鉴而来的方程式:

这里写图片描述

public static int LCS(String one, String two) {        int[][] c = new int[one.length() + 1][two.length() + 1];        for (int i = 1; i <= one.length(); i++) {            for (int j = 1; j <= two.length(); j++) {                if (one.charAt(i - 1) == two.charAt(j - 1)) {                    c[i][j] = c[i - 1][j - 1] + 1;                } else {                    c[i][j] = Math.max(c[i - 1][j], c[i][j - 1]);                }            }        }        return c[one.length()][two.length()];    }

今天碰到了一道题:

一个合法的括号匹配序列被定义为:
1. 空串”“是合法的括号序列
2. 如果”X”和”Y”是合法的序列,那么”XY”也是一个合法的括号序列
3. 如果”X”是一个合法的序列,那么”(X)”也是一个合法的括号序列
4. 每个合法的括号序列都可以由上面的规则生成
例如”“, “()”, “()()()”, “(()())”, “(((()))”都是合法的。
从一个字符串S中移除零个或者多个字符得到的序列称为S的子序列。
例如”abcde”的子序列有”abe”,”“,”abcde”等。
定义LCS(S,T)为字符串S和字符串T最长公共子序列的长度,即一个最长的序列W既是S的子序列也是T的子序列的长度。
小易给出一个合法的括号匹配序列s,小易希望你能找出具有以下特征的括号序列t:
1、t跟s不同,但是长度相同
2、t也是一个合法的括号匹配序列
3、LCS(s, t)是满足上述两个条件的t中最大的
因为这样的t可能存在多个,小易需要你计算出满足条件的t有多少个。
如样例所示: s = “(())()”,跟字符串s长度相同的合法括号匹配序列有:
“()(())”, “((()))”, “()()()”, “(()())”,其中LCS( “(())()”, “()(())” )为4,其他三个都为5,所以输出3.

这里写图片描述

思路:
合法的括号序列其实就是合法的出栈入栈操作,变相的求卡特兰数,这里可以用递归求解。然后生成的括号字符串分别与输入的括号字符串进行求最长公共子序列。

import java.util.Scanner;public class 最长公共子括号序列 {    public static int MAX = 0;    public static int NUM = 0;    public static void main(String[] args) {        Scanner scanner = new Scanner(System.in);        String string = scanner.nextLine().trim();        scanner.close();        int length = string.length();        make("", length / 2, length / 2, string);        System.out.println(NUM);    }    public static void make(String s, int leftnum, int rightnum, String string) {        if (leftnum == 0 && rightnum == 0) {            if (!s.equals(string)) {                int max = LCS(s, string);                if (max == MAX)                    NUM++;                if (max > MAX) {                    MAX = max;                    NUM = 1;                }            }        }        if (leftnum > 0) {            make(s + "(", leftnum - 1, rightnum, string);        }        if (rightnum > 0 && leftnum < rightnum) {            make(s + ")", leftnum, rightnum - 1, string);        }    }    public static int LCS(String one, String two) {        int[][] c = new int[one.length() + 1][two.length() + 1];        for (int i = 1; i <= one.length(); i++) {            for (int j = 1; j <= two.length(); j++) {                if (one.charAt(i - 1) == two.charAt(j - 1)) {                    c[i][j] = c[i - 1][j - 1] + 1;                } else {                    c[i][j] = Math.max(c[i - 1][j], c[i][j - 1]);                }            }        }        return c[one.length()][two.length()];    }}
原创粉丝点击