【字符串处理算法】获取最长公共子串的算法设计及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.如果输入的两个字符串之一含有空格,那么程序获取空格之前的字符串进行后续操作。

 

四、程序代码

 

/**********************************************************************
* 版权所有 (C)2016, Zhou Zhaoxiong。
*
* 文件名称: GetLCS.c
* 文件标识: 无
* 内容摘要: 寻找两个字符串的最长公共子串
* 其它说明: 例如, "abcdef"和"bcf"的最长公共子串是"bc"
* 当前版本: V1.0
* 作    者: Zhou Zhaoxiong
* 完成日期: 20160322
*
**********************************************************************/
#include 
   
   
    
    
#include 
    
    
     
     
#include 
     
     
      
      


// 重新定义数据类型
typedef signed   char  INT8;
typedef          int   INT32;
typedef unsigned int   UINT32;

// 函数声明
void GetLCSOfTwoStr(INT8 *pszInputStr1, INT8 *pszInputStr2);


/**********************************************************************
* 功能描述: 主函数
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 0-执行成功   其它-执行失败
* 其它说明: 无
* 修改日期        版本号     修改人            修改内容
* ---------------------------------------------------------------------
* 20160322        V1.0     Zhou Zhaoxiong        创建
***********************************************************************/
INT32 main()
{
    INT8   szInputStr1[100] = {0};
    INT8   szInputStr2[100] = {0};
    UINT32 iPosFlag        = 0;
    
    printf("Please input string1: \n");
    scanf("%s", szInputStr1);
    printf("InputStr1=%s\n", szInputStr1);

    printf("Please input string2: \n");
    scanf("%s", szInputStr2);
    printf("InputStr2=%s\n", szInputStr2);

    // 先判断是否有中文字符
    for (iPosFlag = 0; iPosFlag < strlen(szInputStr1); iPosFlag ++)
    {
        if (szInputStr1[iPosFlag] < 0)     // 小于0则表示含有中文字符
        {
            printf("%s has Chinese character, please check!\n", szInputStr1);
            return -1;
        }
    }

    for (iPosFlag = 0; iPosFlag < strlen(szInputStr2); iPosFlag ++)
    {
        if (szInputStr2[iPosFlag] < 0)     // 小于0则表示含有中文字符
        {
            printf("%s has Chinese character, please check!\n", szInputStr2);
            return -1;
        }
    }

    // 再调用函数获取两个字符串的最长公共子串
    GetLCSOfTwoStr(szInputStr1, szInputStr2);

    return 0;
}


/**********************************************************************
* 功能描述: 获取两个字符串的最长公共子串
* 输入参数: pszInputStr1-输入字符串1
             pszInputStr2-输入字符串2
* 输出参数: 无
* 返 回 值: 无
* 其它说明: 无
* 修改日期        版本号     修改人            修改内容
* ---------------------------------------------------------------------
* 20160322        V1.0     Zhou Zhaoxiong        创建
***********************************************************************/
void GetLCSOfTwoStr(INT8 *pszInputStr1, INT8 *pszInputStr2)
{
    UINT32 iInnerLoopFlag  = 0;
    UINT32 iOutterLoopFlag = 0;
    UINT32 iPosFlag        = 0;
    UINT32 iLCSLen         = 0; 
    INT32  iStartPos       = -1;
    INT8   szLCS[100]      = {0};
    
    if (pszInputStr1 == NULL || pszInputStr2 == NULL)
    {
        return;
    }

    for (iOutterLoopFlag = 0; iOutterLoopFlag < strlen(pszInputStr1); iOutterLoopFlag ++)
    { 
        for (iInnerLoopFlag = 0; iInnerLoopFlag < strlen(pszInputStr2); iInnerLoopFlag ++)
        { 
            if (pszInputStr1[iOutterLoopFlag] == pszInputStr2[iInnerLoopFlag])
            { 
                for (iPosFlag = 1; pszInputStr1[iOutterLoopFlag+iPosFlag] != '\0'; iPosFlag ++)
                {
                    if (pszInputStr1[iOutterLoopFlag+iPosFlag] != pszInputStr2[iInnerLoopFlag+iPosFlag]) // 遇到不相等的字符, 则退出比较
                    {
                        break;
                    }
                }

                if (iLCSLen < iPosFlag)
                { 
                    iLCSLen   = iPosFlag; 
                    iStartPos = iOutterLoopFlag; 
                } 
            } 
        } 
    } 
  
    if (iStartPos == -1)
    { 
        memset(szLCS, 0x00, sizeof(szLCS)); 
    }
    else
    { 
        memcpy(szLCS, &pszInputStr1[iStartPos], iLCSLen); 
    } 

    if (iLCSLen > 0)
    {
        printf("%s和%s的最长公共子串是:%s, 其长度是:%d\n", pszInputStr1, pszInputStr2, szLCS, iLCSLen);
    }
    else
    {
        printf("%s和%s无公共子串!\n", pszInputStr1, pszInputStr2);
    }  
}


     
     
    
    
   
   

 

五、程序测试

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

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

Please input string1:

abcdef

InputStr1=abcdef

Please input string2:

hijkabm

InputStr2=hijkabm

abcdefhijkabm的最长公共子串是:ab, 其长度是:2

 

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

Please input string1:

1234!@#

InputStr1=1234!@#

Please input string2:

5678!@#1

InputStr2=5678!@#1

1234!@#5678!@#1的最长公共子串是:!@#, 其长度是:3

 

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

Please input string1:

123你们好

InputStr1=123你们好

Please input string2:

123

InputStr2=123

123你们好 has Chinese character, pleasecheck!

 

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

Please input string1:

123abc

InputStr1=123abc

Please input string2:

abd ef

InputStr2=abd

123abcabd的最长公共子串是:ab, 其长度是:2

 

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

Please input string1:

abcdef

InputStr1=abcdef

Please input string2:

123456

InputStr2=123456

abcdef123456无公共子串!

 

六、需求扩展

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

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

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知识的港湾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值