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


    1.两个字符串的最长公共子串与最长公共子序列的区别:

    最长公共子串要求在原字符串中是连续的,而子序列只需要保持相对顺序一致,并不要求连续。

    下面分别讲讲怎么求它们。

    2.最长公共子串:

    (1)暴力解法:

    要求最长公共子串,可以用暴力的解法:

    int longestSubstring(string x, string y) {
        int max = 0;
        string str = "";
        for (int i = 0; i < x.size(); i++) {
            int len = 0;
            int j = i;
            while (j < x.size()) {
                str += x[j];
                if (y.find(str) == y.npos) break;
                len++;
                j++;
                if (len > max) max = len;
            }
            str = "";
        }
        return max;   
    }

    或者:

    int longestSubstring(string x, string y) {
        int xlen = x.size();
        int ylen = y.size();
        if (xlen == 0 || ylen == 0) {
            return 0;   
        }
        int max = -1;
        for (int i = 0; i < xlen; i++) {
            for (int j = 0; j < ylen; j++) {
                int m = i, n = j;
                int len = 0;
                while (m < xlen && n < ylen) {
                    if (x[m] != y[n]) {
                        break;
                    }
                    m++;
                    n++;
                    len++;
                }
                if (len > max) {
                    max = len;
                }
            }
        }
        return max;
    }

    这种暴力解法唯一值得学习的地方,就是怎么求一个字符串的所有子字符串。用一个二层循环即可,外面一层循环从字符串的头遍历到尾,里面的循环就从当前的位置开始,每个字符地加,这样就可以得到所有的子字符串了。

    (2)动态规划:

    状态转移方程:

    最长公共子串长度就为max{c[i][j]}了,代码如下:

    int longestSubstring(string x, string y) {
       vector<vector<int> > f(x.size() + 1, vector<int>(y.size() + 1, 0));
       int max = -1;
       for (int i = 1; i <= x.size(); i++) {
           for (int j = 1; j <= y.size(); j++) {
               if (x[i - 1] != y[j - 1]) f[i][j] = 0;
               else if (x[i - 1] == y[j - 1]) f[i][j] = f[i - 1][j - 1] + 1;
               if (max < f[i][j]) {
                 max = f[i][j];
               }
           }
        }
        return max;
    }

    (3)后缀数组解法

    有这么一个解法,但我没有看过。

    3.最长公共子序列

    直接用动态规划解决,转移方程为:

     代码:

    int longestSubstring(string x, string y) {
        int **dp = new int*[x.size() + 1];
        for (int i = 0; i < x.size(); i++) {
            dp[i] = new int[y.size() + 1];
        }
        for (int i = 0; i <= x.size(); i++) dp[i][0] = 0;
        for (int i = 0; i <= y.size(); i++) dp[0][i] = 0;
        for (int i = 1; i <= x.size(); i++) {
            for (int j = 1; j <= y.size(); j++) {
                if (x[i] == y[j]) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                }
                else {
                    dp[i][j] = dp[i - 1][j] > dp[i][j - 1] ? dp[i - 1][j] : dp[i][j - 1];
                }
            }
        }
        return dp[x.size()][y.size()];
    }
  • 相关阅读:
    回文链表
    istringstream
    编写函数,以读模式打开一个文件,将其内容读入到一个string的vector中,将每一行作为一个对立的元素存于vector中
    c++ primer,友元函数上的一个例子(By Sybase)
    类的静态成员
    聚合类和字面值常量类
    隐式的类类型转换
    构造函数
    类的作用域
    类的其他特性
  • 原文地址:https://www.cnblogs.com/fengziwei/p/7827959.html
Copyright © 2020-2023  润新知