79 最长公共子串

原题网址:https://www.lintcode.com/problem/longest-common-substring/description

描述

给出两个字符串,找到最长公共子串,并返回其长度。

 

子串的字符应该连续的出现在原字符串中,这与子序列有所不同。

您在真实的面试中是否遇到过这个题?  

样例

给出A=“ABCD”,B=“CBCE”,返回 2

挑战

O(n x m) time and memory.

标签
字符串处理
LintCode 版权所有
 
思路:依旧是动态规划。
 
建立二维数组dp,同最长公共子序列一样,为了计算方便,二维数组大小为 A.size()+1 × B.size()+1。则 dp【i】【j】表示以 A【i-1】和 B【j-1】为结尾字符的公共子串的最大长度。(注意这里和公共子序列不同,dp【i】【j】不是A中 0~i-1 和 B 中 0~j-1的最长公共子串)
 
状态转移方程:若 A【i-1】和 B【j-1】相等,dp【i】【j】=dp【i-1】【j-1】+1;否则,dp【i】【j】=0。(因为不相等,所以不存在以这两个字符为结尾的公共子串)
 
详细讲解:假设两个字符串分别为s和t,s[i]t[j]分别表示其第i和第j个字符(字符顺序从0开始),再令L[i, j]表示以s[i]和t[j]为结尾的相同子串的最大长度。应该不难递推出L[i, j]L[i+1,j+1]之间的关系,因为两者其实只差s[i+1]t[j+1]这一对字符。
s[i+1]t[j+1]不同,那么L[i+1, j+1]自然应该是0,因为任何以它们为结尾的子串都不可能完全相同;
而如果s[i+1]t[j+1]相同,那么就只要在以s[i]t[j]结尾的最长相同子串之后分别添上这两个字符即可,这样就可以让长度增加一位。
合并上述两种情况,也就得到L[i+1,j+1]=(s[i]==t[j]?L[i,j]+1:0)这样的关系。 转自此文: 从优化到再优化,最长公共子串   文章写得很好,可以多看几遍。
 
AC代码
class Solution {
public:
    /**
     * @param A: A string
     * @param B: A string
     * @return: the length of the longest common substring.
     */
    int longestCommonSubstring(string &A, string &B) {
        // write your code here
    int n1=A.size(),n2=B.size();
     if (n1==0||n2==0)
     {
         return 0;
     }
     vector<vector<int>> dp(n1+1,vector<int>(n2+1,0));
    int maxl=-1;
     for (int i=1;i<=n1;i++)
     {
         for (int j=1;j<=n2;j++)
         {
            if (A[i-1]==B[j-1])
            {
                dp[i][j]=dp[i-1][j-1]+1;
            }
            maxl=max(maxl,dp[i][j]);
         }
     }

     return maxl;
    }
};

 

 
 
 
posted @ 2018-07-13 21:30  eeeeeeee鹅  阅读(234)  评论(0编辑  收藏  举报