算法导论—最长公共子串

华电北风吹
日期:2016/2/22

题目描述:
找两个字符串的最长公共子串是一个很简单的问题,注意这里的子串必须连续。

解题思路:
例如对于字符串abcb和字符串cbc可以构建如下二维矩阵,匹配为1不匹配为0即可。这样直接看主对角线上连续1的最大长度即可。
    c  b  c
a  0  0  0
b  0  1  0
c  1  0  1
b  0  1  0
对于主对角线上连续1的个数可以使用动态规划求解。在这里不妨直接把动态规划的思路添加到二维矩阵的构建里面。在构建的时候如果发现匹配了,就对这个元素赋值为它左上角的元素加1即可(具体见下面表格)。这样存储过程中由于只用相邻两行,所以用两行矩阵就够了。需要注意的是需要时刻对最大值进行判别保存。
   c  b  c
a  0  0  0
b  0  1  0
c  1  0  2
b  0  2  0

参考代码:

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

class Solution
{
public:
    string LCS(const string& str1, const string& str2)
    {
        int len1 = str1.size();
        int len2 = str2.size();
        vector<int> state1(len2 + 1);
        vector<int> state2(len2 + 1);

        vector<int> *pStateNew = NULL, *pStateLast = NULL;
        bool flag = false;

        int pos = 0, maxlen = 0;

        for (int i = 0; i<len1; i++)
        {
            if (flag == false)
            {
                pStateLast = &state1;
                pStateNew = &state2;
            }
            else
            {
                pStateLast = &state2;
                pStateNew = &state1;
            }
            for (int j = 1; j <= len2; j++)
            {
                if (str1[i] == str2[j - 1])
                    (*pStateNew)[j] = (*pStateLast)[j - 1] + 1;
                else
                    (*pStateNew)[j] = 0;
                if ((*pStateNew)[j] > maxlen)
                {
                    pos = j;
                    maxlen = (*pStateNew)[j];
                }
            }
            flag = !flag;
        }
        string res = str2.substr(pos - maxlen, maxlen);
        return res;
    }
};

int main()
{
    string str1("abcb");
    string str2("cbc");
    Solution s;
    string lcs = s.LCS(str1, str2);
    cout << lcs << endl;
    return 0;
}

你可能感兴趣的:(算法导论—最长公共子串)