最長公共子串和最長公共子序列


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()];
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM