zoukankan      html  css  js  c++  java
  • kmp

       在暴力匹配两个字符串时,如果匹配失败,文本串跳到刚开始匹配的下一位置,模式串跳到开头。

    暴力匹配具体步骤:

    1. 如果匹配成功,则++i,++j,继续匹配下一字符;
    2. 如果匹配失败,i=i-(j-1),j=0,即i回溯,j置0(从头再来)
    int violentMatch(const string& s,const string& p)
    {
        int sLen=s.size();
        int pLen=p.size();
        int i=0,j=0;
        while(i<sLen&&j<pLen)
        {
            if(s[i]==p[j])
            {
                ++i;
                ++j;
            }
            else
            {
                i=i-j+1;
                j=0;
            }
        }
        return j==pLen?i-j:0;
    }

      为了减少时间复杂度,在kmp算法中,匹配失败时文本串不动,移动模式串来进行下次匹配,模式串的移动位置靠next数组来决定。

      next 数组各值的含义:代表当前字符之前的字符串中,有多大长度的相同前缀后缀。例如如果next [j] = k,代表j 之前的字符串中有最大长度为k 的相同前缀后缀。此也意味着在某个字符失配时,该字符对应的next 值会告诉你下一步匹配中,模式串应该跳到哪个位置(跳到next [j] 的位置)。如果next [j] 等于0或-1,则跳到模式串的开头字符,若next [j] = k 且 k > 0,代表下次匹配跳到j 之前的某个字符,而不是跳到开头,且具体跳过了k 个字符。

    kmp具体步骤:

    1. 如果j==-1(模式串跳到第一个字符)或 当前位置模式串和文本串匹配成功:则++i,++j;
    2. 如果next[j]>0,则模式串跳到以j结尾字符串的最长前缀和最长后缀相等的位置,即j=next[j]。
    #include <iostream>
    #include <vector>
    using namespace std;
    
    class Kmp
    {
    private:
        vector<int> next;//next[i],以i结尾(不包含i)的最长前缀和后缀相等的值
    private:
        void getNext(const string& p)//求模式串的next数组
        {
            int pLen=p.size();
            next.resize(pLen,0);
            next[0]=-1;
            next[1]=0;
            int flag=0;
            for(int i=2;i<pLen;)
            {
                if(p[flag]==p[i-1])
                    next[i++]=++flag;
                else if(flag>0)
                    flag=next[flag];
                else
                    next[i++]=0;
            }
            return ;
        }
    public:
        int kmp(const string& s,const string& p)
        {
            getNext(p);
            int i=0,j=0;
            int sLen=s.size(),pLen=p.size();
            while(i<sLen&&j<pLen)
            {
                if(s[i]==p[j])
                {
                    ++i;
                    ++j;
                }
                else if(next[j]==-1)//j移动到模式串的第一个字符,即j==0
                {
                    ++i;
                }
                else
                {
                    j=next[j];
                }
            }
            //与下列等效
            #if 0
            while(i<sLen&&j<pLen)
            {
                if(j==-1||s[i]==p[j])
                {
                    ++i;
                    ++j;
                }
                else
                {
                    j=next[j];
                }
            }
            #endif // 0
            return j==pLen?i-j:0;
        }
    };
    int main()
    {
        Kmp k;
        cout<<k.kmp("BBC ABCDAB ABCDABCDABDE","ABCDABD")<<endl;
        return 0;
    }
  • 相关阅读:
    让我偷偷的告诉你:运维加薪的杀手锏是啥?
    网站页面优化必然趋势—WebP 图片!
    如何监控 Tomcat?Zabbix 与 Cloud Insight 对比
    网页增重不可控?试试 OneAPM Cloud Test
    提高 ASP.NET Web 应用性能的 24 种方法和技巧
    OneAlert 入门(三)——事件分析
    Cloud Insight 客户案例-晨芯时代科技有限公司
    Java开发快速上手
    微信小程序快速开发上手
    微信小程序快速开发上手
  • 原文地址:https://www.cnblogs.com/tianzeng/p/10544782.html
Copyright © 2011-2022 走看看