最长公共子串

题:给定两个字符串X,Y,求二者最长的公共子串,例如X=[aaaba],Y=[abaa]。二者的最长公共子串为[aba],长度为3。

1 基本算法
其实对于最长公共子串,还是比较简单易想的,因为子串是连续的,这就方便了很多。
最直接的方法就是用X每个子串与Y的每个子串做对比,求出最长的公共子串。

2  DP方案
既然最长公共子串是最长公共子序列的变体,那么最长公共子串是不是也可以用动态规划来求解呢?
我们还是像之前一样“从后向前”考虑是否能分解这个问题,在最大子数组和中,
我们也说过,对于数组问题,可以考虑“如何将arr[0,...i]的问题转为求解arr[0,...i-1]的问题”,
类似最长公共子序列的分析,这里,我们使用dp[i][j]表示 以x[i]和y[j]结尾的最长公共子串的长度,
因为要求子串连续,所以对于X[i]与Y[j]来讲,它们要么与之前的公共子串构成新的公共子串;要么就是不构成公共子串。
故状态转移方程
X[i] == Y[j],dp[i][j] = dp[i-1][j-1] + 1
X[i] != Y[j],dp[i][j] = 0
对于初始化,i==0或者j==0,如果X[i] == Y[j],dp[i][j] = 1;否则dp[i][j] = 0。

#include<stdio.h>
#include<string.h>


void outputLCS(char * X);

// 最长公共子串 Longest Common Substring 
int maxlen;    //记录最大公共子串长度 
int maxindex;  // 记录最大公共子串在串1的起始位置 
void outputLCS(char * X);  // 输出LCS 

// 最长公共子串 基本算法 ===================
int comlen(char * p, char * q)
{
    int len = 0;
    while(*p && *q && *p++ == *q++)
    {
        ++len;
    }
    return len;
}
 
void LCS_base(char * X, int xlen, char * Y, int ylen)
{
    for(int i = 0; i < xlen; ++i)
    {
        for(int j = 0; j < ylen; ++j)
        {
            int len = comlen(&X[i],&Y[j]);
            if(len > maxlen)
            {
                maxlen = len;
                maxindex = i;
            }
        }
    }
    outputLCS(X);
}


// 最长公共子串 DP ======================================
int dp[30][30];
 
void LCS_dp(char * X, int xlen, char * Y, int ylen)
{
    maxlen = maxindex = 0;
    for(int i = 0; i < xlen; ++i)
    {
        for(int j = 0; j < ylen; ++j)
        {
            if(X[i] == Y[j])
            {
                if(i && j)//i>0 && j>0
                {
                    dp[i][j] = dp[i-1][j-1] + 1;
                }
                if(i == 0 || j == 0)
                {
                    dp[i][j] = 1;
                }
                if(dp[i][j] > maxlen)
                {
                    maxlen = dp[i][j];
                    maxindex = i + 1 - maxlen;
                }
            }
        }
    }
    outputLCS(X);
}



//============  common code =============================

void outputLCS(char * X)
{
    if(maxlen == 0)
    {
        printf("NULL LCS
");
        return;
    }
    printf("The len of LCS is %d
",maxlen);
 
    int i = maxindex;
    while(maxlen--)
    {
        printf("%c",X[i++]);
    }
    printf("
");
}
 
void main()
{
    char X[] = "aaaba";
    char Y[] = "abaa";
 
    /* 基本算法 */
    LCS_base(X,strlen(X),Y,strlen(Y));
 
    /* DP算法 */
    LCS_base(X,strlen(X),Y,strlen(Y));
 
}


原文地址:https://www.cnblogs.com/sjw1357/p/3863990.html