最长公共字符串(longest common substring)和最长公共字序列(longest common subsequence)解法之比较

问题描述:

最长公共子串:给定两个字符串s1,s2,求两个串公共的子串;

最长公共子序列:给定两个字符串s1,s2, 其两个串公共的子序列,即按照从头到尾的顺序,寻找两个串共有的字符集(不要求连续);


问题解法:

下面分别给出两个问题的暴力解法,递归解法,动态规划解法:

         1.暴力解法;

         2.递归解法:(因为重复计算太多,导致巨慢无比);

        3.动态规划:(最好的方法)


代码如下:

 = /
//  Header.h
//  Algorithm
//
//  Created by wang steven on 4/23/14.
//  Copyright (c) 2014 wang steven. All rights reserved.
//

#ifndef Algorithm_Header_h
#define Algorithm_Header_h


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


/*
 * helper function malloc memeory for two dimension array
 *
 */
void ConstructTable( int*** table, int width, int height )
{
    
    int** curTable = (int**)malloc( height * sizeof(int*) );
    int* buffer = (int*)malloc(height * width * sizeof(int));
    
    
    for( int i = 0; i < height; i++ )
    {
        curTable[i] = buffer + i * width;
    }
    
    *table = curTable;
}


/*
 * helper function release memory
 *
 */
void DestructTable( int** table )
{
    free( table[0] );
    free( table );
}


/*
 * the implementation of longest common substring of brute force method
 *
 */
int longCommonSubstrBrute( const char* firstStr, const char* secondStr, char subStr[] )
{
    size_t firstLen = strlen( firstStr );
    size_t secondLen = strlen( secondStr );
    
    int maxLen = -1;
    int maxIdx = -1;
    int len = 0;
    for( int i = 0; i < firstLen; i++)
    {
        int start = i;
        for( int j = 0; j < secondLen; j++ )
        {
            if( firstStr[start] == secondStr[j] )
            {
                start++;
                len++;
            }
            else
            {
                if( len > maxLen )
                {
                    maxLen = len;
                    maxIdx = i;
                }
                
                len = 0;
                start = i;
            }
        }
        
    }
    
    if( maxIdx >= 0 && maxLen > 0 )
        memcpy( subStr, &firstStr[maxIdx], maxLen );
    
    return maxLen;
    
    
}



/*
 * the implementation of longest common substring of dynamic programming method
 *
 */
int longCommonSubstr( const char* firstStr, const char* secondStr, char subStr[] )
{
    size_t firstLen = strlen( firstStr );
    size_t secondLen = strlen( secondStr );
    
    int** table = 0;
    ConstructTable( &table, firstLen + 1, secondLen + 1);
    
    
    int maxLen = -1;
    int startIdx1 = -1;
    int startIdx2 = -1;
    
    for( int i = 0; i <= firstLen; i++ )
    {
        for( int j = 0; j <= secondLen; j++ )
        {
            if(  0 == i || 0 == j )
            {
                table[0][0] = 0;
                continue;
            }
            else if( firstStr[i-1] == secondStr[j-1] )
            {
                table[i][j] = table[i - 1][j - 1] + 1;
                if( maxLen < table[i][j] )
                {
                    maxLen = table[i][j];
                    startIdx1 = i - maxLen;
                    startIdx2 = j - maxLen;
                    
                }
            }
            else
            {
                table[i][j] = 0;
            }
        }
    }
    

    memcpy( subStr, &firstStr[startIdx1], maxLen );
    
    DestructTable( table );
    
    return maxLen;
}





/*
 * the implementation of longest common subsequence of recursive method
 *
 */
int longCommonSubseqRecur( const char* firstStr, const char* secondStr, int posFirst, int posSecond )
{
    if( '\0' == firstStr[posFirst] ||  '\0' == secondStr[posSecond] )
        return 0;
    
    if( firstStr[posFirst] == secondStr[posSecond] )
    {
        return 1 + longCommonSubseqRecur(firstStr, secondStr, posFirst + 1, posSecond   + 1 );
    }
    else 
    {
        int k1 = longCommonSubseqRecur( firstStr, secondStr, posFirst + 1, posSecond );
        int k2 = longCommonSubseqRecur( firstStr, secondStr, posFirst, posSecond + 1 );
        
        if( k1 > k2 )
            return k1;
        
        return k2;
    }
}

/*
 * the implementation of longest common subsequence of brute force method
 *
 */
int longCommonSubseq( const char* firstStr, const char* secondStr )
{
    size_t firstLen = strlen( firstStr );
    size_t secondLen = strlen( secondStr );
    
 
    int** table = 0;
    ConstructTable( &table, firstLen, secondLen );
    
    
    for( int i = 0; i < firstLen; i++ )
    {
        table[i][0] = 0;
    }

    for( int i = 0; i < secondLen; i++ )
    {
        table[0][i] = 0;
    }

    for( int i = 1; i < firstLen; i++ )
    {
        for( int j = 1; j < secondLen; j++ )
        {
            if( firstStr[i] == secondStr[j] && table[i][j] < table[i-1][j-1] + 1)
            {
                table[i][j] = table[i-1][j-1] + 1;
            }
            else
            {
                if( table[i-1][j] > table[i][j-1] )
                {
                    table[i][j] = table[i-1][j];
                }
                else
                {
                    table[i][j] = table[i][j-1];

                }
            }
        }
    }
    
    int res = table[firstLen - 1][secondLen - 1];
    DestructTable( table );
    
    return res;
    
}


void TestLongCommonSubseq()
{
    const char* str3 = "abcdefossweightkk";
    const char* str4 = "abdkweighttuus";
    int kk = longCommonSubseqRecur( str3, str4, 0, 0);
    printf("%d\n", kk );
    
    
    //int res1 = longCommonSubseq( str3, str4);
    //printf("%d \n", res1);
}


void TestLongCommonSubstr()
{
    const char* str1 = "www.sina.com.cn.www.google.com.hk,dcccoweightformomentchinawoiwieoioweioweiowe";
    const char* str2 = "woewiweiwiwemicrosoftowiejdkdweightformomentchinawwoweiweiewiewiruiowehohghgalalglcdds";
    
    char substr[1024] = {0};
    int res = longCommonSubstr( str1, str2, substr );
    if( res > 0 )
    {
        printf("output longest common substring is %s \n", substr );
    }
    

    
    memset( substr, 0x00, sizeof(substr) );
    int resb = longCommonSubstrBrute(str1, str2, substr );
    if( resb > 0 )
    {
        printf("output longest common substring is %s \n", substr );
    }
    
    assert( res == resb );
    
}


void TestLCS()
{
    TestLongCommonSubseq();
    TestLongCommonSubstr();
}


#endif


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,针对你的问题,我来给你解答。 首先,最长公共序列Longest Common Subsequence,简称 LCS)指的是给定两个字符串,找到它们之间最长公共序列的长度。而最长公共字符串Longest Common Substring,简称 LPS)指的是给定两个字符串,找到它们之间最长公共字符串。 接下来,我分别介绍如何求解这两个问题。 1. 最长公共序列(LCS) 求解最长公共序列的问题可以使用动态规划的思想来解决。具体的,我们可以定义一个二维数组 dp,其中 dp[i][j] 表示第一个字符串的前 i 个符和第二个字符串的前 j 个符之间的最长公共序列长度。则状态转移方程为: - 当 s1[i-1] == s2[j-1] 时,dp[i][j] = dp[i-1][j-1] + 1。 - 当 s1[i-1] != s2[j-1] 时,dp[i][j] = max(dp[i-1][j], dp[i][j-1])。 最终的最长公共序列长度即为 dp[m][n],其中 m 和 n 分别为两个字符串的长度。 同时,我们可以通过倒推 dp 数组,求出最长公共序列具体是哪些符。 2. 最长公共字符串(LPS) 求解最长公共字符串的问题也可以使用动态规划的思想来解决。具体的,我们可以定义一个二维数组 dp,其中 dp[i][j] 表示以第一个字符串的第 i 个符和第二个字符串的第 j 个符结尾的最长公共字符串的长度。则状态转移方程为: - 当 s1[i-1] == s2[j-1] 时,dp[i][j] = dp[i-1][j-1] + 1。 - 当 s1[i-1] != s2[j-1] 时,dp[i][j] = 0。 最终的最长公共字符串长度为 dp[i][j] 中的最大值,其中 i 和 j 分别为最长公共字符串在两个字符串中的结尾位置。 同时,我们也可以通过倒推 dp 数组,求出最长公共字符串具体是哪些符。 希望我的回答能够帮助到你。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值