zoukankan      html  css  js  c++  java
  • [笔记]:[字符串] kmp算法 标签: kmp算法 2017-05-12 19:46 83人阅读 评论(0)

    KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息。时间复杂度O(m+n)。
    中文名 KMP算法
    外文名 The Knuth-Morris-Pratt Algorithm
    输入 正文串T[1,n]和模式串W[1,m]
    输出 匹配结果match[1,n]
    发现者 D.E.Knuth等
    时间复杂度 O(m+n)
    先对t串进行预处理 算出next数组
    在与s串进行kmp
    在写的时候记得将next写成Next 不然交上去CE 下面程序就不改了
    下面的代码也是[poj 3461]的答案

    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    #define N 1000010
    using namespace std;
    int next[N],ans,ls,lt;
    char s[N],t[N];
    int n;
    void makenext()
    {
        next[1]=0;  int k=0,j=1;
        while(j<=lt){
            if(k==0||t[j]==t[k]){
                j++;k++;
                next[j]=k;
            }
            else k=next[k];
        }
    }
    void fnd()
    {
        int i=1,j=1;
        while(i<=ls)
        {
            if(s[i]==t[j]||j==0){i++;j++;}
            else j=next[j];
            if(j>lt) {j=next[j];ans++;}
        }
    }
    int main()
    {
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            ans=0;
            memset(s,0,sizeof(s)); memset(t,0,sizeof(t));
            s[0]='0';t[0]='0';
            scanf("%s",t+1);
            scanf("%s",s+1);
            ls=strlen(s)-1,lt=strlen(t)-1;
            makenext();
            fnd();
            cout<<ans<<endl;
        }
        return 0;
    }
    

    改进版 对于aaaab这种情况
    如第4个不匹配直接跳回第一个a
    不用找第3个第2个a浪费时间

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #define N 1000
    using namespace std;
    int next[N],ans,ls,lt;
    char s[N],t[N];
    int n;
    void makenext(){
        next[1]=0;
        int k=0,j=1;
        while(j<=lt){
            if(k==0||t[j]==t[k]){
                j++;k++;
                if(t[k]==t[j]) next[j]=next[k];//aaaab 这种情况 
                else
                next[j]=k;
            }
            else k=next[k];
        }
    }
    void fnd(){
        int i=1,j=1;
        while(i<=ls){
            if(j==0||s[i]==t[j]){
                i++;j++;
            }
            else j=next[j];
            if(j>lt) {j=next[j];ans++;}
        }
    }
    int main(){
        gets(s+1);
        gets(t+1);
        ls=strlen(s+1);
        lt=strlen(t+1);
        return 0;
    }
  • 相关阅读:
    解决使用OCI连接oracle LNK2019: 无法解析的外部符号的问题
    VS2010下配置OCI编程
    OpenLayers简单介绍以及简单实例
    浏览器的标准模式与怪异模式的设置与区分方法
    解决ie7不支持after、before的方法
    ie7兼容after、before的方法
    【移动端适配】适配1个像素的border
    js实现对table的增加行和删除行的操作
    css3线性渐变:linear-gradient
    使用iScroll实现上、下滑动刷新和加载更多数据
  • 原文地址:https://www.cnblogs.com/xljxlj/p/7183667.html
Copyright © 2011-2022 走看看