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;
    }
};

 

posted @ 2020-12-07 19:32  不妨不妨,来日方长  阅读(208)  评论(0编辑  收藏  举报