求两个字符串的最长公共子串(初学者适用)

求两个字符串的最长公共子串(初学者适用)

何为公共子串?

即两个字符串中相等连续的子串。
例如:串“abcde”和串“gabfcde”中公共子串有ab”和“cde”两个。

何为最长公共子串呢?

即在上述“公共子串”的定义中加上最长二字, 上面例子中“cde”便是最长公共子串

基本算法思想

大致思路

假设有串str1和串str2。挨个找出str1和str2中所有的公共子串,在寻找过程中只记录下长度最长的公共子串。

  1. 先固定其中一个字符串(此处将str1固定),取其第一个字符str1[0],查找str1和str2中有没有以该字符开头的公共子串:
    将str[0]与str2中的字符挨个比较,若遇到相等的,再接着比较str1和str2中相等字符的下一个位置,直至遇到下一对不相等的字符,即完成一个公共子串的搜寻。例如:
    在这里插入图片描述

    若该公共子串的长度大于之前搜寻到的公共子串长度,则将原有的覆盖掉(始终保留长度最大的公共子串),之后继续查找,将str1[0]与str2中的剩余字符逐一比较。

  2. 之后再依次取出str1中的第2个、第3个…第n个字符,重复上述操作,当str1中的所有字符均取出和str2中的字符遍历比较后,此时所记录下来的公共子串即为所求的最长公共子串。

实现代码

这是我个人的思想,可能理解起来有点麻烦,但还是想把它记录下来


`#include<stdio.h>
#include<string.h>
typedef struct //设置一个栈来记录下每次找到的公共子串
{
 int num;
 char str[100];
}Stack;
void Init(Stack &s)//在查找完一个公共子串后,需要将栈初始化,以存放下一个公共子串的信息
{
 s.num=0;
 for(int i=0;i<100;++i)
  s.str[i]=0;
}
char s[100]={0};//存放最长公共子串
void find(Stack s1,char *str1,char *str2)
{
 for(int i=0;i<strlen(str1);++i)
 {
  int k=i,j=0;//k是i的替身,防止i变化,j用于str2中的字符
  while(j<strlen(str2))
  {
   if(str1[k]==str2[j])//相等时,将相等字符记录下来,并移动k和i
   {
    s1.str[(s1.num)++]=str1[k];
    ++k;++j;
   }
   else
   {
    if(strlen(s1.str)>strlen(s))//不相等时,若已经找到一个公共子串,则判断该公共子串与原有公共子串的长度大小,保留长度较大者
    {
     for(t=0;t<strlen(s1.str);++t)
      s[t]=s1.str[t];
    }
    if(strlen(s1.str))//如果前面存在公共子串,说明k已经不是str1中取出的第i个字符了,在进行下一次比较前,需将其置为i
     k=i;
    else  //否则就一直挨个与str2中的字符进行比较
     ++j;
    Init(s1);//下一次查找前,对其初始化(清空掉上一次的公共子串信息)
   }
  }
 }
}
int main()
{
 Stack s1;Init(s1);
 char str1[]="abcdkkk";
 char str2[]="baabcdadabc";
 find(s1,str1,str2);
 printf("%d\n",strlen(s));
 puts(s);
 return 0;
}

结束啦!不容易

  • 5
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值