400 028 6601

建站动态

根据您的个性需求进行定制 先人一步 抢占小程序红利时代

C++实现字符串查找KMP算法-创新互联

前言

刚接触KMP算法时,你大概会觉得这个算法非常诡异,一波诡异的操作处理后生成了一个next数组,又一波诡异的遍历操作后,就找到了目标位置(???WTF);
代码倒是不长,每个单词都认识,但是放一块就不认识了,像极了四级英语阅读。。

创新互联建站主营金溪网站建设的网络公司,主营网站建设方案,成都app开发,金溪h5微信小程序搭建,金溪网站营销推广欢迎金溪等地区企业咨询一、需要提前明白的概念 1. 大前后缀

首先你需要知道大前后缀是什么;

以下图为例:在箭头位置上,它的前置大前后缀为abb
图1.1

以下图为例:在箭头位置上,它的前置大前后缀为abbsab
图1.2

看到这里你可能会有疑惑,大前后缀的规则是什么?下面简单进行一个总结:

  1. 大前缀 与 大后缀必须相等。
  2. 大前后缀必须小于它可取的长度;即:图一中大前后缀不能同时取abbsabb(s以前的所有字符),图二中大前后缀不能取b以前的所有字符,那样的话就失去了它的意义。
  3. 大前后缀必须尽可能的长;图二中可能相等的前后缀有:ababbsabb,我们需要取其中较大的那个。
2.next数组

至于next数组是哪里来的,有什么用?会放在后面讲。

二、主逻辑 1.主要步骤:

这里先展示一下如何使用大前后缀

这一步,过滤了暴力解法的主串指针回溯过程
那么为什么可以这么跳过呢?
主要分两个证明:

  1. 前后缀相等,则字符串跳转后,下标位置处 前字串也一定匹配
  2. 跳转经过的区间内,一定不存在与主串匹配的存在

问题一自不用说,肉眼可见,下面主要证明步骤2;为什么经过区间一定不含可能匹配的存在

2.跳跃方式

以上就是主串的整个匹配过程。
计算可得:这个过程的大时间复杂度不超过O(2 * N)

3.主要代码
int strStr(string str1, string str2) {vectornext;
        func(next, str2);					//求next数组

        int idx1 = 0;
        int idx2 = 0;
        while(idx1< str1.size())
        {if(str1[idx1] == str2[idx2])	//匹配上就两个指针一起往下走
            {idx1++;
                idx2++;
                if(idx2 == str2.size())
                {return idx1 - idx2;
                }
            }
            else if(idx2 == 0)				//没匹配上而且idx2在0位置
            {idx1++;
            }
            else{	//没匹配上  idx2不在0位置
                idx2 = next[idx2];
            }
        }
        return -1;
    }
三、求next数组1.总过程

我不论如何,先给next数组填一个0
图3.1

图3.7
继续重复上述过程:
图3.8
图3.9
图3.10
以上就是整个next数组的求解过程,主要采用动态规划的形式,以类似主逻辑的方式将整个next数组求解。

四、代码
class Solution {//求next 数组
    void func(vector& next, string& str2)
    {next.resize(0);
        next.push_back(0);
        int idx1 = 1;
        int idx2 = 0;
        while(idx1< str2.size())
        {//相等则next填充,两指针自增
            if(str2[idx1] == str2[idx2])
            {next.push_back(++idx2);
                idx1++;
            }//格式串在最左部,
            else if(idx2 == 0)
            {next.push_back(0);
                idx1++;
            }
            else{//可以向前找
                idx2 = next[idx2 - 1];
            }
        }
    }
public:
	int strStr(string str1, string str2) {vectornext;
        func(next, str2);					//求next数组

        int idx1 = 0;
        int idx2 = 0;
        while(idx1< str1.size())
        {if(str1[idx1] == str2[idx2])	//匹配上就两个指针一起往下走
            {idx1++;
                idx2++;
                if(idx2 == str2.size())
                {return idx1 - idx2;
                }
            }
            else if(idx2 == 0)				//没匹配上而且idx2在0位置
            {idx1++;
            }
            else{	//没匹配上  idx2不在0位置
                idx2 = next[idx2];
            }
        }
        return -1;
    }
}

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


网站名称:C++实现字符串查找KMP算法-创新互联
分享网址:http://mzwzsj.com/article/cdoojo.html

其他资讯

让你的专属顾问为你服务