最长公共子序列、子串

1、最长公共子序列

c[i][j]表示Xi和Yi的最长公共子序列的长度
状态转移方程:

          0, i=0 || j=0
c[i][j]=  c[i-1][j-1]+1, xi=yi
          max(c[i-1][j],c[i][j-1]),xi != yi

代码实现:

class MaxSubSequence {
    char[] ch1;
    char[] ch2;
    int[][] c;
    int[][] s;
    List<Character> result = new ArrayList<>();
    Set<List<Character>> allResult = new HashSet<>();

    public MaxSubSequence(String s1, String s2) {
        this.ch1 = ArrayStartFromOne(s1.toCharArray());
        this.ch2 = ArrayStartFromOne(s2.toCharArray());
        this.c = new int[ch1.length][ch2.length];
        this.s = new int[ch1.length][ch1.length];
    }

    public char[] ArrayStartFromOne(char[] arr) {
        char[] newArr = new char[arr.length + 1];
        for (int i = 0; i < arr.length; i++) {
            newArr[i + 1] = arr[i];
        }
        newArr[0] = '0';
        return newArr;
    }

    public int getSubSequence() {
        int m = ch1.length;
        int n = ch2.length;
        int i, j;
        // 当一列为空时,公共序列为0
        for (i = 1; i < m; i++)
            c[i][0] = 0;
        for (j = 1; j < n; j++)
            c[0][j] = 0;
        for (i = 1; i < m; i++) {
            for (j = 1; j < n; j++) {
                if (ch1[i] == ch2[j]) {
                    c[i][j] = c[i - 1][j - 1] + 1;
                    s[i][j] = 1;
                } else if (c[i - 1][j] > c[i][j - 1]) {
                    c[i][j] = c[i - 1][j];
                    s[i][j] = 2;

                } else {
                    c[i][j] = c[i][j - 1];
                    s[i][j] = 3;
                }
            }
        }
        return c[m - 1][n - 1];
    }

    public void getLCS() {
        int i = ch1.length - 1;
        int j = ch2.length - 1;
        while (i > 0 && j > 0) {
            if (s[i][j] == 1) {
                result.add(ch1[i]);
                // 左斜上方前进
                i--;
                j--;
            } else if (s[i][j] == 2) {
                // 向上前进
                i--;
            } else {
                // 向左前进
                j--;
            }
        }
    }

    public int getSubSequence2() {
        int m = ch1.length;
        int n = ch2.length;
        int[][] c = new int[m][n];// 0到m,长度为m+1
        int i, j;
        // 当一列为空时,公共序列为0
        for (i = 1; i < m; i++) {
            for (j = 1; j < n; j++) {
                if (ch1[i] == ch2[j]) {
                    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[m - 1][n - 1];
    }

2、最长公共子串

转台转移方程:

          0, i=0 || j=0
c[i][j]=  c[i-1][j-1]+1, xi=yi
          0,xi != yi
public static int maxSubLength(int[] A, int[] B) {
    int m = A.length, n = B.length;
    int ans = 0;
    int[][] c = new int[m + 1][n + 1];
    for (int i = 1; i <= A.length; i++)
        for (int j = 1; j <= B.length; j++) {
            if (A[i - 1] == B[j - 1]) {
                c[i][j] = c[i - 1][j - 1] + 1;
                ans = Math.max(c[i][j], ans);
            } else {
                c[i][j] = 0;
            }
        }
    return ans;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值