问题描述:
最长公共子串:给定两个字符串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