最長公共字符串(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


發佈了30 篇原創文章 · 獲贊 0 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章