一.问题描述:
最长公共子串 (LCS-Longest Common Substring) LCS问题就是求两个字符串最长公共子串的问题。比如输入两个字符串"ilovechina"和“chinabest”的最长公共字符串有"china",它们的长度是5.
二.解法
解法就是用一个矩阵来记录两个字符串中所有位置的两个字符之间的匹配情况,若是匹配则为1,否则为0。然后求出对角线最长的1序列,其对应的位置就是最长匹配子串的位置。如下图:
i l o v e c h i n a
c 0 0 0 0 0 1 0 0 0 0
h 0 0 0 0 0 0 1 0 0 0
i 1 0 0 0 0 0 0 1 0 0
n 0 0 0 0 0 0 0 0 1 0
a 0 0 0 0 0 0 0 0 0 1
b 0 0 0 0 0 0 0 0 0 0
e 0 0 0 0 1 0 0 0 0 0
s 0 0 0 0 0 0 0 0 0 0
t 0 0 0 0 0 0 0 0 0 0
由于要得到结果还要找到此矩阵中最长的1对角线序列即上图中的红色部分,需要花一定的时间,于是出现了下面的改进,
i l o v e c h i n a
c 0 0 0 0 0 1 0 0 0 0
h 0 0 0 0 0 0 2 0 0 0
i 1 0 0 0 0 0 0 3 0 0
n 0 0 0 0 0 0 0 0 4 0
a 0 0 0 0 0 0 0 0 0 5
b 0 0 0 0 0 0 0 0 0 0
e 0 0 0 0 1 0 0 0 0 0
s 0 0 0 0 0 0 0 0 0 0
t 0 0 0 0 0 0 0 0 0 0
改进算法:当字符匹配的时候,我们并不是简单的给相应元素赋上1,而是赋上其左上角元素的值加一。我们用个标记变量来标记矩阵中值最大的元素的位置,在矩阵生成的过程中来判断当前生成的元素的值是不是最大的,据此来改变标记变量的值,那么到矩阵完成的时候,最长匹配子串的位置和长度就已经出来了。
代码:
1 #define M 100 2 char *myLCS(char *str1,char *str2) 3 { 4 /** 遍历两个字符串每个字符串中的每个字符都和另一个字符串中的所有字符判断 */ 5 // 1. 获取两个字符串长度 6 int length1 = (int)strlen(str1); 7 int length2 = (int)strlen(str2); 8 // 2. 创建并初始化矩阵 9 int matrix[M][M] = {0}; 10 /*int **matrix = (int **)malloc(sizeof(int*)*length1); 11 for (int i = 0; i< length1;i++) 12 { 13 matrix[i] = (int *)malloc(sizeof(int)*length2); 14 }*/ 15 int startIndex = 0; 16 int endIndex = 0; 17 int maxLenth = 0; 18 19 // 3. 遍历 20 for (int i = 0; i < length1; i++) 21 { 22 for (int j = 0; j < length2; j++) 23 { 24 if (str1[i] == str2[j]) 25 { 26 // 第一行 或 第一列 相等的初始化为1 其余以他们左上角值加1 27 if ((i == 0) || (j == 0)) 28 { 29 matrix[i][j] = 1; 30 } 31 else // 左上角的值加1 32 { 33 matrix[i][j] = matrix[i-1][j-1] + 1; 34 } 35 } 36 else // 不相等置为0 37 { 38 matrix[i][j] = 0; 39 } 40 if (matrix[i][j] > maxLenth) 41 { 42 maxLenth = matrix[i][j]; 43 endIndex = j; 44 } 45 } 46 } 47 // 起始位置 = 结束位置 - maxlength + 1; 48 startIndex = endIndex - maxLenth +1; 49 for (int k = 0; k < maxLenth; k++) 50 { 51 printf("%c",str2[startIndex++]); 52 } 53 return str1; 54 }
测试代码:
1 int main(int argc, const char * argv[]) { 2 3 char *s1 = "ilovechina"; 4 char *s2 = "chinabest"; 5 myLCS(s1,s2); 6 return 0; 7 }
结果:
china