【字符串处理算法】获取最长公共子串的算法设计及C代码实现

开发 开发工具 算法
今天讲讲获取最长公共子串的算法设计及C代码实现的知识。

一、需求描述

输入两个字符串,编写程序获取这两个字符串的***个最长公共子串。

例如,输入的字符串为“abcdef”和“fecdba”,那么这两个字符串的***个最长公共子串为“cd”。

二、算法设计

我们可以首先寻找两个字符串中的***个相等的字符,然后分别向后移动来比较对应位置的字符是否相等。

即如果字符串1为“1234abcd”,字符串2为“abd”,那么首先发现字符串1中的第五个字符“a”与字符串2中的***个字符“a”相等,接着字符串1中的第六个字符“b”与字符串2中的第二个字符“b”相等,再接着发现字符串1中的第七个字符“c”与字符串2中的第三个字符“d”不相等,此时比较结束。也就是说字符串1和字符串2的最长公共子串为“ab”。

算法

三、特殊流程考虑

在编写程序的过程中,我们要对输入的字符串的长度及格式多做考虑,如:

1.如果输入的两个字符串之一含有中文字符,那么程序直接返回而不执行后续流程。

2.如果输入的两个字符串之一含有空格,那么程序获取空格之前的字符串进行后续操作。

 

四、程序代码

  1. /********************************************************************** 
  2. * 版权所有 (C)2016, Zhou Zhaoxiong。 
  3. * 文件名称: GetLCS.c 
  4. * 文件标识: 无 
  5. * 内容摘要: 寻找两个字符串的最长公共子串 
  6. * 其它说明: 例如, "abcdef"和"bcf"的最长公共子串是"bc" 
  7. * 当前版本: V1.0 
  8. * 作    者: Zhou Zhaoxiong 
  9. * 完成日期: 20160322 
  10. **********************************************************************/ 
  11. #include <stdio.h> 
  12. #include <string.h> 
  13. #include <stdlib.h> 
  14.  
  15.  
  16. // 重新定义数据类型 
  17. typedef signed   char  INT8; 
  18. typedef          int   INT32; 
  19. typedef unsigned int   UINT32; 
  20.  
  21. // 函数声明 
  22. void GetLCSOfTwoStr(INT8 *pszInputStr1, INT8 *pszInputStr2); 
  23.  
  24.  
  25. /********************************************************************** 
  26. * 功能描述: 主函数 
  27. * 输入参数: 无 
  28. * 输出参数: 无 
  29. * 返 回 值: 0-执行成功   其它-执行失败 
  30. * 其它说明: 无 
  31. * 修改日期        版本号     修改人            修改内容 
  32. * --------------------------------------------------------------------- 
  33. * 20160322        V1.0     Zhou Zhaoxiong        创建 
  34. ***********************************************************************/ 
  35. INT32 main() 
  36.     INT8   szInputStr1[100] = {0}; 
  37.     INT8   szInputStr2[100] = {0}; 
  38.     UINT32 iPosFlag        = 0
  39.      
  40.     printf("Please input string1: \n"); 
  41.     scanf("%s", szInputStr1); 
  42.     printf("InputStr1=%s\n", szInputStr1); 
  43.  
  44.     printf("Please input string2: \n"); 
  45.     scanf("%s", szInputStr2); 
  46.     printf("InputStr2=%s\n", szInputStr2); 
  47.  
  48.     // 先判断是否有中文字符 
  49.     for (iPosFlag = 0; iPosFlag < strlen(szInputStr1); iPosFlag ++) 
  50.     { 
  51.         if (szInputStr1[iPosFlag] < 0)     // 小于0则表示含有中文字符 
  52.         { 
  53.             printf("%s has Chinese character, please check!\n", szInputStr1); 
  54.             return -1; 
  55.         } 
  56.     } 
  57.  
  58.     for (iPosFlag = 0; iPosFlag < strlen(szInputStr2); iPosFlag ++) 
  59.     { 
  60.         if (szInputStr2[iPosFlag] < 0)     // 小于0则表示含有中文字符 
  61.         { 
  62.             printf("%s has Chinese character, please check!\n", szInputStr2); 
  63.             return -1; 
  64.         } 
  65.     } 
  66.  
  67.     // 再调用函数获取两个字符串的最长公共子串 
  68.     GetLCSOfTwoStr(szInputStr1, szInputStr2); 
  69.  
  70.     return 0; 
  71.  
  72.  
  73. /********************************************************************** 
  74. * 功能描述: 获取两个字符串的最长公共子串 
  75. * 输入参数: pszInputStr1-输入字符串1 
  76.              pszInputStr2-输入字符串2 
  77. * 输出参数: 无 
  78. * 返 回 值: 无 
  79. * 其它说明: 无 
  80. * 修改日期        版本号     修改人            修改内容 
  81. * --------------------------------------------------------------------- 
  82. * 20160322        V1.0     Zhou Zhaoxiong        创建 
  83. ***********************************************************************/ 
  84. void GetLCSOfTwoStr(INT8 *pszInputStr1, INT8 *pszInputStr2) 
  85.     UINT32 iInnerLoopFlag  = 0
  86.     UINT32 iOutterLoopFlag = 0
  87.     UINT32 iPosFlag        = 0
  88.     UINT32 iLCSLen         = 0;  
  89.     INT32  iStartPos       = -1; 
  90.     INT8   szLCS[100]      = {0}; 
  91.      
  92.     if (pszInputStr1 == NULL || pszInputStr2 == NULL) 
  93.     { 
  94.         return; 
  95.     } 
  96.  
  97.     for (iOutterLoopFlag = 0; iOutterLoopFlag < strlen(pszInputStr1); iOutterLoopFlag ++) 
  98.     {  
  99.         for (iInnerLoopFlag = 0; iInnerLoopFlag < strlen(pszInputStr2); iInnerLoopFlag ++) 
  100.         {  
  101.             if (pszInputStr1[iOutterLoopFlag] == pszInputStr2[iInnerLoopFlag]) 
  102.             {  
  103.                 for (iPosFlag = 1; pszInputStr1[iOutterLoopFlag+iPosFlag] != '\0'; iPosFlag ++) 
  104.                 { 
  105.                     if (pszInputStr1[iOutterLoopFlag+iPosFlag] != pszInputStr2[iInnerLoopFlag+iPosFlag]) // 遇到不相等的字符, 则退出比较 
  106.                     { 
  107.                         break; 
  108.                     } 
  109.                 } 
  110.  
  111.                 if (iLCSLen < iPosFlag
  112.                 {  
  113.                     iLCSLen   = iPosFlag;  
  114.                     iStartPos = iOutterLoopFlag;  
  115.                 }  
  116.             }  
  117.         }  
  118.     }  
  119.    
  120.     if (iStartPos == -1) 
  121.     {  
  122.         memset(szLCS, 0x00, sizeof(szLCS));  
  123.     } 
  124.     else 
  125.     {  
  126.         memcpy(szLCS, &pszInputStr1[iStartPos], iLCSLen);  
  127.     }  
  128.  
  129.     if (iLCSLen > 0) 
  130.     { 
  131.         printf("%s和%s的最长公共子串是:%s, 其长度是:%d\n", pszInputStr1, pszInputStr2, szLCS, iLCSLen); 
  132.     } 
  133.     else 
  134.     { 
  135.         printf("%s和%s无公共子串!\n", pszInputStr1, pszInputStr2); 
  136.     }   

五、程序测试

我们将编写好的程序“GetLCS.c”上传到Linux机器,并使用“gcc -g -o GetLCS GetLCS.c”命令对该程序进行编译,生成“GetLCS”文件。下面对程序进行详细的测试。

1.输入字符串1为“abcdef”,字符串2为“hijkabm”时,程序运行情况如下:

  1. Please input string1: 
  2. abcdef 
  3. InputStr1=abcdef 
  4. Please input string2: 
  5. hijkabm 
  6. InputStr2=hijkabm 
  7. abcdef和hijkabm的最长公共子串是:ab, 其长度是:2 

2.输入字符串1为“1234!@#”,字符串2为“5678!@#1”时,程序运行情况如下:

  1. Please input string1: 
  2. 1234!@# 
  3. InputStr1=1234!@# 
  4. Please input string2: 
  5. 5678!@#1 
  6. InputStr2=5678!@#1 
  7. 1234!@#和5678!@#1的最长公共子串是:!@#, 其长度是:3 

3.输入字符串1为“123你们好”,字符串2为“123”时,程序运行情况如下:

  1. Please input string1: 
  2. 123你们好 
  3. InputStr1=123你们好 
  4. Please input string2: 
  5. 123 
  6. InputStr2=123 
  7. 123你们好 has Chinese character, pleasecheck! 

4.输入字符串1为“123abc”,字符串2为“abd ef”时,程序运行情况如下:

  1. Please input string1: 
  2. 123abc 
  3. InputStr1=123abc 
  4. Please input string2: 
  5. abd ef 
  6. InputStr2=abd 
  7. 123abc和abd的最长公共子串是:ab, 其长度是:2 

5.输入字符串1为“abcdef”,字符串2为“123456”时,程序运行情况如下:

  1. Please input string1: 
  2. abcdef 
  3. InputStr1=abcdef 
  4. Please input string2: 
  5. 123456 
  6. InputStr2=123456 
  7. abcdef和123456无公共子串! 

六、需求扩展

基于本文中的需求和程序,我们可考虑对需求进行以下扩展:

1.如果两个字符串有多于一个最长公共子串,则都要将它们输出,即如果字符串1为“1234abcd”,字符串2为“abd12”,那么程序输入的最长公共子串为“12”和“ab”。

 

2.不限制输入字符串中不能出现中文字符,即如果字符串1为“我们123”,字符串2为“我们”,那么最长公共子串为“我们”。

【本文是51CTO专栏作者周兆熊的原创文章,作者微信公众号:周氏逻辑(logiczhou)】

戳这里,看该作者更多好文

责任编辑:赵宁宁 来源: 51CTO专栏
相关推荐

2016-12-30 13:32:24

字符串算法代码

2016-12-29 17:07:59

字符算法代码

2016-12-30 13:16:51

字符串算法代码

2016-12-29 17:14:41

回文串算法代码

2016-12-30 13:37:50

字符串算法代码

2023-02-26 22:33:32

字符串排列算法

2009-08-11 10:26:49

C#算法C#字符串反转

2016-12-29 16:25:32

字符串算法代码

2021-09-02 09:22:13

算法无重复字符

2013-05-06 10:54:08

字符串字符串匹配KMP算法

2023-12-15 10:27:01

暴力匹配算法Python字符串

2021-09-03 09:41:36

字符串时间复杂度

2021-11-12 09:44:03

字符串算法复杂度

2023-04-11 08:54:57

字符串匹配算法

2013-05-06 10:49:21

Boyer-Moore算法字符串匹配

2021-09-10 08:31:54

翻转字符串单词

2021-11-19 09:00:24

LeetCode字符串算法

2021-12-17 08:51:41

LeetCode最长公共前缀算法

2021-11-15 07:47:40

字符串位置存储

2010-11-26 09:51:54

MySQL字符串
点赞
收藏

51CTO技术栈公众号