最長公共子串

/***********************************************************************
 *description:最長公共子串
 *            給定兩個字符串str1和str2,返回兩個字符串的最長公共子串
 *            如:str1=“1AB2345CD” str2=“12345EF”
 *                返回“2345”

 ***********************************************************************/

#include <iostream>
#include <string>
#include <vector>
using namespace std;

//方法1:時間複雜度O(M*N),空間複雜度O(M*N)
//經典動態規劃問題,數組dp[M][N]
//dp[i][j]代表str1[i]和str2[j]當做公共子串最後元素的最大長度
//dp[i][0]:str1[i]==str2[0]時才爲1,否則爲0
//dp[0][j]:str1[0]==str2[j]時才爲1,否則爲0
//dp[i][j]:
//          1.str1[i]!=str2[j],dp[i][j]=0
//          2.str1[i]==str2[j],dp[i][j]=dp[i-1][j-1]+1
//得到dp之後,遍歷找到最大的元素及其位置,然後str1的該位置向前索引即可。
string longestSharedSubStr_1(string str1, string str2)
{
    string res;
    int M = str1.size();
    int N = str2.size();
    if (M == 0 || N == 0)
        return res;

    vector<vector<int>> dp(M,N);

    for (int i = 0; i < M; i++)
    {
        dp[i][0] = 0;
        if (str1[i] == str2[0])
            dp[i][0] = 1;
    }
    for (int j = 0; j < N; j++)
    {
        dp[0][j] = 0;
        if (str1[0] == str2[j])
            dp[0][j] = 1;
    }
    for (int i = 1; i < M; i++)
    {
        for (int j = 1; j < N; j++)
        {
            if (str1[i] != str2[j])
                dp[i][j] = 0;
            else
                dp[i][j] = dp[i-1][j-1] + 1;
        }
    }
    int len = 0;
    int endIdx = 0;
    for (int i = 0; i < M - 1; i++)
    {
        for (int j = 0; j < N; j++)
        {
            if (dp[i][j] > len)
            {
                len = dp[i][j];
                endIdx = i;
            }
        }
    }
    return str1.substr(endIdx - len + 1, len);

}
//方法2:時間複雜度O(M*N),空間複雜度O(1)
//在方法1的基礎上進行優化。
//每次計算dp[i][j]時,只和dp[i-1][j-1]相關,所以每次按斜線計算,只用一個變量空間。
//然後用個全局變量記錄len和endIdx
string longestSharedSubStr_2(string str1, string str2)
{
    int M = str1.size();
    int N = str2.size();
    if (M == 0 ||  N == 0)
        return "";

    int len = 0;
    int endIdx = 0;
    int last = 0;

    int col = N -1;
    int row = 0;
    while (row < M)
    {
        last = 0;
        int i = row;
        int j = col;
        while (i < M && j < N)
        {
            if (str1[i] == str2[j])
            {
                last++;
            }
            if (last > len )
            {
                len = last;
                endIdx = i;
            }
            i++;
            j++;
        }
        if (col > 0)
            col--;
        else
            row++;
    }

    return str1.substr(endIdx - len + 1, len);

}

int main()
{
    string str1 = "1AB2345CD";
    string str2 = "12345EF";

    cout << longestSharedSubStr_2(str1, str2);
    return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章