KMP算法和原来的暴力匹配算法解析

有一个文本字符串s,和一个模式串p,想要查找s中是否包含p,以及s中p出现的第一个位置。
首先用暴力匹配,主要是不相等的时候就回溯,这样时间复杂度较高。
核心思想i和j分别指向s和p,如果s[i] == p[j]  {i++,j++,count++}
如果count == p.size()就说明找到了;如果s[i] != p[i],此时回溯,i = i-j+1;j=0;
代码如下:
    int findStrWithoutKMP(string s,string p)
    {
        if(s.size() == 0 || p.size() == 0 || s.size() < p.size()) return -1; //表示不存在 s的长度要大于等于p
        int i =0;
        int j =0;

        int curLen = 0;

        while (i>=0 && i<s.size())
        {
            //cout<<"This i is "<<i<<" j is "<<j<<endl;
            curLen = 0;
            for(int j=0;j<p.size();) //j++不需要在这里+
            {
                if(s[i] == p[j] && i<s.size() && j<p.size()) //加上 i<s.size()和j<p.size这个判断和快速排序left right判断一个道理
                {
                    curLen++;
                    //cout<<"This i is "<<i<<" j is "<<j<<" This curLen is "<<curLen<<endl;
                    if(curLen == p.size()) //先进行curLen判断 再进行i++和j++
                    {
                        return (i-p.size()+1) + 1; //i-p.size()+1是从0开始的位置 等于2表示是0 1 2位置所以从1开始实际是第3个,所以再加个1
                    }
                    i++; 
                    j++;
                } else
                {
                    i = i-j+1;
                    j = 0;
                    break;
                }
                
            }
        }
        return -1;

    }
下面再说先kmp算法,kmp算法核心就是利用next数组,是的文本串s不回溯,一直向前,模式串p根据next数组来回溯到对应的位置。
next数组的求法和kmp主函数的有一定类似。这个kmp函数返回的是s中所有包括p的位置,可能有多个,位置从0开始。主要代码如下:
    vector<int>  next(string s)
    {
        vector<int> res(s.size(),0);
        if(s.size() == 0) return res;
 
        int count = 0;
        for(int i=1;i<s.size();i++)
        {
            while (count > 0 && s[i] != s[count])
            {
                count = res[count -1];
            }
            if(s[i] == s[count])
            {
                count++;
            }
            res[i] = count;
        }

        return res;

    }
    

        //00011212001212000                       
    //string s = "abcaababdfababfds";
    //string p = "abab";
    //int findIndexStr(string )
    vector<int> searchByKMP(string s,string p)
    {
        vector<int> positions;
        vector<int> nextVector = next(s); //这个vector命名居然不能和原来的一样

                /************************************
        for(int i=0;i<nextVector.size();i++)
        {
            cout<<nextVector[i]<<" ";
        }
        cout<<endl;
                ************************************/ 
        int count = 0;
        for(int i=0;i<s.size();i++)
        {
            while (count > 0 && p[count] != s[i])
            {
                count = nextVector[count-1];
            }
            
            if(p[count] == s[i])
            {
                count++;
            }

            if(count == p.size())
            {
                positions.push_back(i - p.size()+1);
                count = nextVector[count-1]; //关键这一行是为啥
            }
        }

        return positions;

    }



全部评论

相关推荐

不愿透露姓名的神秘牛友
今天 10:52
点赞 评论 收藏
分享
点赞 评论 收藏
分享
11-09 14:54
已编辑
华南农业大学 产品经理
大拿老师:这个简历,连手机号码和照片都没打码,那为什么关键要素求职职位就不写呢? 从上往下看,都没看出自己到底是产品经理的简历,还是电子硬件的简历? 这是一个大问题,当然,更大的问题是实习经历的描述是不对的 不要只是去写实习流程,陈平,怎么去开会?怎么去讨论? 面试问的是你的产品功能点,是怎么设计的?也就是要写项目的亮点,有什么功能?这个功能有什么难处?怎么去解决的? 实习流程大家都一样,没什么优势,也没有提问点,没有提问,你就不得分 另外,你要明确你投的是什么职位,如果投的是产品职位,你的项目经历写的全都是跟产品无关的,那你的简历就没用 你的面试官必然是一个资深的产品经理,他不会去问那些计算机类的编程项目 所以这种四不像的简历,在校招是大忌
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务