查找之字符串匹配

本文介绍了两种模式匹配算法:简单模式匹配算法和KMP算法。简单模式匹配算法通过逐个比较字符来查找模式串,而KMP算法则通过利用next数组减少不必要的比较,提高了查找效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. 简单的模式匹配算法
     a. 基本思想:从主串S指定的字符开始和模式串T的第一个字符比较,若相等,则继续逐个比较后续字符串,直到T中的每个字符依次和S中的一个连续的字符序列相等,则匹配成功。若比较途中某对字符不想等,则从主串S的下一个字符开始比较。如果S串比较完,仍没匹配成功,则称匹配不成功。
      b. 代码
    int Index(SString S, SString T)
        {
            int i=1,j=1;
            while(i<=S[0]&&j<=T[0])
            {
                if(S[i]==T[j])
                {++i;++j;}       //比较下一字符
                else {i=i-j+2;j=1;}     //指针后退重新开始匹配。
            }
        }

c. 该方法容易,不用过多说明最坏时间复杂度O(n*m)

2. KMP算法(改进的模式匹配算法)
   a. (这个是比较重要的字符串匹配模式) 基本思想:上面朴素匹配方法典型有很大的问题,在一次比较不成功后,直接回溯i指针。KMP算法的改进方式就是比较字符串不匹配时,无需回溯i指针,利用已得到的“部分匹配”的结果将模式向右”滑动“尽可能远的一段距离后,继续进行比较。怎样尽可能滑的远,这就值得讨论了。
   b. 解决方法
KMP算法的每趟比较让子串向后滑动一个合适的位置(next数组求解),让这个位置上的字符和主串中的那个字符比较,这个合适的位置与子串本身结构有关。
   c. 子串T的next[]数组求解. ( 很尴尬,本想搜执行图贴上来,还是手写一下图形了 )

 next数组:
 (1)next[1]=0.next[2]=1.   (next[0]不使用)
 (2)后面求解每一位的next[j]值时,根据j的前一位进行比较,令k=next[j-1];
 (3)将T[j-1]与T[k]进行比较:
     a.如果相等,则该next[j] = k+1;
     b.如果不等,令k=next[k],若k不等于0,跳至(3)。若k等于0,next[j]=1.

代码:

void get_next(char T[],int next[]){
          i=1;
          next[1]=0;
          j=0;
          while(i<=T[0]){           //T[0]保存字符串长度
              if(j==0||T[i]==T[j]){
                  ++i;++j;next[i]=j;}
             else   j=next[j];  
          }//while
      }

手写例子如下
这里写图片描述

d. KMP匹配算法
   形式上与简单的模式匹配算法很相似,不同之出就是匹配失败时,指针i不变,指针j退回next[j]的位置上,再重新进行比较。并且当指针j为0时,指针i和j同时加1(即主串第i个位置和模式串的第一个字符不等时,应从主串的第i+1个位置开始匹配)。
     代码:

int KMP(char S[],char T[],int next[],int pos){
    //利用模式串Tnext数组,求T在主串S中第pos个字符之后的位置的KMP算法
    //其中,T非空,1<= pos <=strlen(S)
    i = pos;
    j = 1;
    while(i<=S[0]&&j<=T[0]){
        if(j==0||S[i]==T[j]){
            ++i;++j;
        }
        else j=next[j];
    }//while
    if(j > T[0])
        return i-T[0];
    else
        return 0;
}

时间复杂度O(n+m)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值