求两个字符串的最大公共子串

面试的时候遇到求两个字符串的最大公共子串,一开始写的很乱,自己都没整明白,现在回想起来,补在这里。

#include<iostream>
using namespace std;
void findMaxSubStr(const char* src,const char *dest)
{
    const char *p=NULL;//存放短的字符串
    const char *q=NULL;
	
	int size_src = 0;
	while('\0' != src[size_src] ){
		size_src++;
	}
	
	int size_dest = 0;
	while('\0' != dest[size_dest] ){
		size_dest++;
	}
	
	if(size_src < size_dest){
		p = src;
		q = dest;
	}else{
		p = dest;
		q = src;
	}
	
	int index = 0, i =0, j = 0,temp=0;
	int start=0,max_len=0;
	while('\0' != p[index]){                                      //p是否到底
		i = index;
		j = 0;
		while('\0' != q[j]){                                  //q是否到底
			while(p[i] != q[j]){                    //不相等
				j++;
				if('\0' == q[j] )
					break;
			}
			if('\0' == q[j] )
				break;
			
			temp = j;
			while(p[i] == q[j]){
				i++;
				j++;
				if('\0' == q[j]){
					break;
				}
				if('\0' == p[i]){
					break;
				}
			}
			if((i-index) > max_len){
				start = index;
				max_len = i - index;
			}
			i = index;
			j = temp + 1;
		}
		index++;
	}
	
	i=0;
	while(i < max_len){
		cout<<p[start+i];
		i++;
		if('\0' == p[start+i]){
			break;
		}
	}
	cout<<endl;
}

int main(void)
{
	char *src = "laskdjflkajsdlfjaslkdjflkasjdlfjasdlkj";
	char *dest = "aksjdklfjalsjdflajsdljfalsjdlfkasldjlfjasldkjflkasjdlkfalsd";
	
	findMaxSubStr(src, dest);
	return 0;
}

google了下,本题解法有很多,可以限制不用指针,用string类。也可以用DP算法解决。也可以用KMP算法。接下来一个一个分析。

#include <iostream>
using namespace std;

int findMaxSubString(const char*src, const char* dest)
{
	int src_len = strlen(src);
	int dest_len = strlen(dest);

	const char *p = ( src_len>=dest_len ) ? src : dest;
	const char *q = ( src_len<dest_len ) ? src : dest;

	int start = 0;
	int max = 0;

	int count = 0;

	int k = 0;
	for(int i = 0; i<=src_len; ++i){
		for(int j = 0; j <=dest_len; ++j){
			k= 0;
			while( i+k<src_len && j+k<dest_len ){
				if( p[i+k]!=q[j+k] ){
					break;	
				}
				++k;
			}
			if( k > max ){
				start = j;
				max = k;
				cout<<"count = "<<++count<<'\t';
			}
		}
	}

	for(int j = start; j < start+max; ++j){
		cout<<q[j];
	}
	cout<<endl;
	cout<<"start = "<<start<<endl;
	cout<<"length   = "<<max<<endl;

	return 0;
}

int main()
{
	char *src = "ksajflkasjdklfjasdlkfjaslkdjflaksdjlfasjdlfdsajlk";
	char *dest = "aksjdhfkjahsdkjgfkadhsfkjsadhfjkshdkjhdsfjakhfdkj";
	findMaxSubString( src, dest );
	return 0;
}

用for循环更清晰,更好理解。

下面是 另一种思路:

#include <cstring>  
#include <iostream>  
using namespace std;  
  
int GetLongestCommonSubString(const char *pStr1, const char *pStr2)  
{  
    /* 判断参数合法性 */  
    if (pStr1 == NULL || pStr2 == NULL) {  
        return -1;  
    }  
  
    int n = strlen(pStr1);  
    int m = strlen(pStr2);  
    int longestCommonSubString = 0;

	int k = 0;

    /* 申请辅助空间,并初始化为0 */  
    int *LCS = new int[m];

    for (int i = 0; i < m; ++i) {  
        LCS[i] = 0;  
    }  
  
    /* 不断判断pStr[i] ?= pStr[j],然后根据不同情况来更新LCS */  
    for ( i = 0; i < n; i++) {  
        for (int j = m - 1; j >= 0; j--) {  
            if (pStr1[i] == pStr2[j]) {    /* 如果pStr1[i] == pStr2[j],LCS[j] = LCS[j-1] + 1 */  
                if (j == 0) {  
                    LCS[j] = 1;  
                } else {  
                    LCS[j] = LCS[j-1] + 1;  
                }  
            } else {                       /* 如果pStr1[i] != pStr2[j],LCS[j] = 0 */   
                LCS[j] = 0;
            }  
  
            /* 更新最长子串的长度 */  
            if (LCS[j] > longestCommonSubString) {  
                longestCommonSubString = LCS[j];
				k = j;
            }  
        }  
    }  
  
    delete LCS;  
    LCS = NULL;

	for( i = 0; i < longestCommonSubString; ++i ){
		cout<<pStr2[ i + k - longestCommonSubString + 1]<<'\t';
	}
  
    return longestCommonSubString;  
}  
  
int main() {
	GetLongestCommonSubString( "sslagdddkjflkdsjlf", "sklagdddkjflasjdlfkasd" );

	return 0;
}

点赞