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

求子序列:(输出字符串长度)

int len1, len2;
const int n = 1002;
int b[n][n];//b[i][j]表示c[i][j]的来源,用于输出最长公共子序列 为1时说明s1[i-1]=s2[j-1] 则可以递归函数print再输出s1[i-1]
//b[i][j]为2时说明s1[i-1]不等于s2[j-1] 最优解来源于c[i][j]=c[i][j-1] 递归输出print(i,j-1)
//为3时说明1[i-1]不等于s2[j-1] 最优解来源于c[i][j]=c[i-1][j] 递归输出print(i-1,j) i或者j为0时递归结束
int c[n][n];//c[len1][len2]表示最长公共子序列的长度
char s1[n], s2[n];

void LCSL() {

    for (int i = 1; i <= len1; i++) 
        for (int j = 1; j <= len2; j++) {
            if (s1[i - 1] == s2[j - 1]) {
                b[i][j] = 1;
                c[i][j] = c[i - 1][j - 1] + 1;
            }
            else if (c[i - 1][j] >= c[i][j - 1]) {
                b[i][j] = 2;
                c[i][j] = c[i - 1][j];
            }
            else {
                b[i][j] = 3;
                c[i][j] = c[i][j - 1];
            }
        }
    
}



        void print(int i, int j) {
            if (i == 0 || j == 0) return;
            if (b[i][j] == 1)
            {
                print(i - 1, j - 1);
                cout << s1[i - 1];
            }
            else if (b[i][j] == 2) {
                print(i - 1, j);
            }
            else
                print(i, j - 1);
        }
int main()

{
   
    cout << "input s1 and s2";
    cin >> s1;
    cout << "s2:";
    cin >> s2;
    len1 = strlen(s1);
    len2 = strlen(s2);
    for (int i = 0; i < len1; i++) {
        for (int j = 0; j < len2; j++) {
            c[0][j] = 0;
            c[i][0] = 0;
        }
    }
    LCSL();
    print(len1, len2);
}


求长度:

  public static int getLCS(char[] x, char[] y) {
        // base case,默认 dp 中的每个元素都为 0。定义dp[i][j]表示字符串str1中第i个字符和str2种第j个字符为最后一个元素所构成的最长公共子串
        int dp[][] = new int[x.length+1][y.length+1];
        
        // 最长公共子串, 用一个临时变量表示
        int resultLCS = 0;
        for (int i = 1; i <= x.length; i++) {
            for (int j = 1; j <= y.length; j++) {
                // 以下是状态转移方程
                if (x[i-1] == y[j-1]) {
                    dp[i][j] = dp[i-1][j-1] + 1;
                    resultLCS = Math.max(resultLCS, dp[i][j]);
                } else {
                    dp[i][j] = 0;
                }
            }
        }
        return resultLCS;
    }

求最长公共子串:若有多个,输出在较短串中最先出现的那个。

 public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        String str1=in.nextLine();
        String str2=in.nextLine();
        String ans="";
    String temp="";
   // 保证str1是较短字符串
        if (str1.length() > str2.length()) {
            temp = str1;
            str1 = str2;
            str2 = temp;
        }
        int m = str1.length() + 1;
        int n = str2.length() + 1;
        // 表示在较短字符串str1以第i个字符结尾,str2中以第j个字符结尾时的公共子串长度。
        int[][] dp = new int[m][n];
        // 匹配字符,并记录最大值的str1的结尾下标
        int max = 0;
        int index = 0;
        // 从左向右递推,i为短字符串str1的结尾索引,j为str2的结尾索引
        for (int i=1; i < m; i++) {
            for (int j=1; j < n; j++) {
                if (str1.charAt(i-1) == str2.charAt(j-1)) {
                    // 相等则计数
                    dp[i][j] = dp[i-1][j-1] + 1;
                    // 不断更新变量
                    if (dp[i][j] > max) {
                        max = dp[i][j];
                        index = i;
                    }
                }
            }
        }
        // 截取最大公共子串
      System.out.println(str1.substring(index-max, index));
    }

你可能感兴趣的:(算法,算法,动态规划)