【C++ 实现字符串的模式匹配算法】

前言

本专栏到这期为止,已经依次介绍了顺序表、链表、数组、栈、队列和二叉树这些数据结构的存储方式以及重要的操作实现。接下来,本期将会讲解字符串的存储方式以及应用:字符串的模式匹配算法

正文

1.字符串

字符串简称串,是由零个或多个字符组成的有限序列。一般记为:

  • S = ‘A1A2A3…An’ (n>=0)
    子串: 串中任意多个相连的字符组成的子序列称为该串的子串。
    主串: 包含子串的串称为该字串的主串。

2.存储结构

串的存储结构可以用三种方式表示:

  • 定长顺序存储表示 (类似定长数组)
  • 堆分配存储表示 (动态申请)
  • 块链存储表示 (类似链式存储)

3.串的模式匹配

子串的定位操作通常称为串的模式匹配,它求的是子串(也称为模式串)在主串中的位置。

//定长顺序存储结构
typedef struct SString{
   int length;
   char ch[255];
   SString(int len,char c[]){
       length = len;
       int i = 0;
       while(c[i] != '\0')
       {
           ch[i] = c[i];
           i++;
       }
   }
};
a.简单的模式匹配算法

思想:暴力求解,通过循环比对两个串的元素。若在主串中找到完整子串,返回子串初始下标。反之,返回-1。
最坏时间复杂度为:O(mn) m,n为两个串的长度。

int MyString::IndexSubstr(SString string1, SString string2)
{
    if(string1.length <=0)
    {
        return -1;
    }
    int i = 0,j = 0;
    while(i<string1.length && j<string2.length)
    {
        char _ch1 = string1.ch[i];
        char _ch2 = string2.ch[j];
        if(_ch1 != _ch2)
        {
            i ++;
            j = 0;
        }
        else
        {
            i ++;
            j ++;
            if(j == string2.length)
            {
                return i-string2.length;
            }
        }

    }
    return -1;
}
b.KMP串的模式匹配算法

思想:相对于朴素的模式匹配算法,KMP算法优化了当模式串匹配失败时的处理
朴素的模式匹配算法中,若字串匹配失败,直接将j的指针退回字串的首个元素位置。此时,并未考虑子串中存在重复前缀的情况。
在这里插入图片描述

//计算模式串失配后,应当跳转比较元素下标
std::vector<int> MyString::computeNext(SString pattern) {
    int m = pattern.length;
    std::vector<int> next(m, 0);
    int i = 1;
    int j = 0;

    while (i < m) {
        if (pattern.ch[i] == pattern.ch[j]) {
            j++;
            next[i] = j;
            i++;
        } else {
            if (j != 0) {
                j = next[j - 1];
            } else {
                next[i] = 0;
                i++;
            }
        }
    }

    return next;
}
//KMP算法,将所有与模式串匹配的下标存储动态数组
std::vector<int> MyString::KMP(SString text, SString pattern) {
    std::vector<int> next = computeNext(pattern);
    std::vector<int> matches;
    int n = text.length;
    int m = pattern.length;
    int i = 0;
    int j = 0;

    while (i < n) {
        if (pattern.ch[j] == text.ch[i]) {
            i++;
            j++;
        }

        if (j == m) {
            matches.push_back(i - j);
            j = next[j - 1];
        } else if (i < n && pattern.ch[j] != text.ch[i]) {
            if (j != 0) {
                j = next[j - 1];
            } else {
                i++;
            }
        }
    }

    return matches;
}
c.KMP算法的优化

针对模式串中出现的连续重复元素,KMP算法中仍然出现对不必要元素的重复访问。对此,我们可以进一步继续优化KMP算法。
后续更新。。。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

葛狂的博客

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

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

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

打赏作者

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

抵扣说明:

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

余额充值