常见算法问题之最长公共子串问题(Longest common substring problem)

对于寻找两个字符串的最长公共子字符串的问题,暴力搜索的方式的时间复杂度将高达O(n^3), 而通过后缀树的方式可将时间复杂度降低到O(n^2)。

以下是我实现的C++源码:

#include <iostream>
#include <string>
#include <vector>

using namespace std;

class Solution
{
public:
    int FindLongestCommonSubstring(string str1, string str2, vector<string>& MaxSubstr)
    {
        int m = str1.length(), n = str2.length(), i, j, k = 0, MaxSubstrLen = 0;
        vector<vector<int>> L(m, vector<int>(n, 0));  // L记录相同子串的长度

        for (i = 0; i < m; i++)
        {
            for (j = 0; j < n; j++)
            {
                if (str1[i] == str2[j])
                {
                    if (i == 0 || j == 0)
                        L[i][j] = 1;
                    else
                        L[i][j] = L[i - 1][j - 1] + 1;

                    if (MaxSubstrLen < L[i][j])
                    {
                        MaxSubstrLen = L[i][j];
                        k = 0;
                        MaxSubstr[k] = str1.substr(i + 1 - MaxSubstrLen, MaxSubstrLen);
                    }
                    else if (MaxSubstrLen == L[i][j] && MaxSubstr[k] != str1.substr(i + 1 - MaxSubstrLen, MaxSubstrLen))  
                        //有多个长度相同的MaxSubstr, 且要排除多个MaxSubstr内容相同的情况,如当str1="a", str2="aaaa"
                        MaxSubstr[++k] = str1.substr(i + 1 - MaxSubstrLen, MaxSubstrLen);
                }
                else
                    L[i][j] = 0;
            }
        }

        return k;
    }
};

int main()
{
    string str1 = "aaabaaaeabcd";
    string str2 = "bbbababcde";
    vector<string> MaxSubstr(str1.length());  //MaxSubstr个数不会超过str1和str2的长度,这里取str1.length
    Solution a;
    int MaxSubstrNum = a.FindLongestCommonSubstring(str1, str2, MaxSubstr);

    for (int i = 0; i <= MaxSubstrNum; i++)
        cout << MaxSubstr[i] << ' ';
    cout << endl;

    return 0;
}

参考:https://en.wikipedia.org/wiki/Longest_common_substring_problem

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值