zoukankan      html  css  js  c++  java
  • KMP算法

    KMP算法解决的是字符串匹配的问题

    文本串:aabaabaaf

    模式串:aabaaf

    判断文本串中是否存在模式串

    需要用到前缀表

      前缀:包含首字母不包含尾字母的所有子串

      后缀:包含为字母不包含首字母的所有子串

    求最长相等前后缀

    初始化

    处理前后缀不相同的情况

    处理前后缀相同的情况

    更新next数组

    i:指向后缀末尾位置

    j:指向前缀末尾位置,还代表i包括i之前子串的最长相等前后缀长度

    初始化:j=0;注意这个位置对j的初始化其实有好几种方式,有的人习惯于赋值-1,也就是对整个next数组进行-1操作;有的习惯于使用原next数组,我比较倾向于next原数组,这二者的差别只在于进行j回溯的时候那句逻辑。

    next[0]=0;

     然后循环里对i进行初始化,循环里头,先判断后缀不相同的情况:不相同的话要对j进行回溯,回溯到前一位对应的回退位置;

    如果前后缀相同,将j++,然后更新next数组。

    这样就完成了next数组的构建。

    然后进行匹配的时候,两个字符串用两个下标分别进行迭代,注意模式串的下标初始值跟next数组起始位置一样,习惯于初始化为0,这也是我为什么倾向于next数组初始化为0的原因;

    还是先处理不匹配的情况,进行回溯;

    匹配的话移动;

    根据不同题目判读不同终止条件。

    class Solution {
    public:
        void getNext(int* next, const string& s)
        {
            int j = 0;//前缀的末尾,统一0操作,所以初始化为0
            next[0] = j;
            for(int i = 1; i < s.size(); i++)
            {
                //先处理前后缀不相等的情况,如果不相等,前缀要进行回退,知道回退到相等或者到模式串开头位置,回退的下标就是当前前缀前一个位置的next数组的值
                while(j > 0 && s[i] != s[j])
                {
                    j = next[j-1];
                }
                //处理前后缀相同的情况,如果相同,i和j都往后移一位,j++,next[i]等于j
                if(s[i] == s[j])
                {
                    j++;
                }
                next[i] = j;
            }
        }
    
        int strStr(string haystack, string needle) {
            //haystack是文本串
            //needle是模式串
            //KMP算法,需要构造next数组
           if(needle.size() == 0)
           {
               return 0;
           }
           int next[needle.size()];
           getNext(next, needle);//得到前缀表
           //得到前缀表之后,需要进行匹配,用j来迭代模式串,用i来迭代文本串
           int j = 0;//因为next数组里是从0开始的
           for(int i = 0; i < haystack.size(); i++)
           {
               //先处理二者不相等的情况,如果不相等,模式串需要回退,按照next数组进行回退
               while(j > 0 && haystack[i] != needle[j])
               {
                   j = next[j-1];
               }
               //如果二者相等,继续向后判断
               if(haystack[i] == needle[j])
               {
                   j++;//i++在循环里头
               }
               //判断是不是模式串在文本串里头的条件:迭代器j已经到了尾部
               if(j == needle.size())
               {
                   return i - needle.size() + 1;
               }
           }
           return -1;
        }
    };
  • 相关阅读:
    吉特仓储管系统(开源WMS)--分享两月如何做到10W+的项目
    吉特仓库管理系统(开源)-如何在网页端启动WinForm 程序
    RequireJS中的require如何返回模块
    RequireJS shim 用法说明
    从ISTIO熔断说起-轻舟网关熔断
    数据库与数据仓库的区别是什么
    API是什么
    要想业务中台建得快,最好用Service Mesh来带
    中台建设之路-中台建设怎么做?建设中台需要具备什么?
    为什么要建设中台
  • 原文地址:https://www.cnblogs.com/masbay/p/14094393.html
Copyright © 2011-2022 走看看