zoukankan      html  css  js  c++  java
  • 给小白看的KMP算法

    浅谈KMP算法:

    (大部分人的KMP写法都是不一样的)

    一:

      先给大家推荐一个讲kmp比较好理解的一个博客:阮一峰

    二:

     下面介绍一点相关概念:

    栗子: 
      P串: ABCBD

      前缀:A,AB,ABC,ABCB,ABCBD 
      真前缀:A,AB,ABC,ABCB 
      后缀:D,BD,CBD,BCBD,ABCBD 
      真后缀:D,BD,CBD,BCBD

    KMP算法里的next数组的含义:

    栗子: 
      P串: ABCDABD 
      next[] = {-1, 0, 0, 0, 0, 1, 2, 0, }; 
      next[i] 的含义:P串前 i 个字符(包括第 i 个)的最长真前缀后缀公共长度;     
      如 i = 5时: 
        真前缀:A,AB,ABC,ABCD 
        真后缀:BCDA,CDA,DA,A

      显而易见, 前缀和后缀相同的只有 A,而 A 的长度为 1,所以next[5] = 1;

    next数组求法:

    //用通俗的语句说就是k是用来表示子串中前k个和后k个是相同的,i是用来遍历数组
    void get_next(char *t,int lent){
        nex[0] = -1;
        for(int i = 0,k = -1;i < lent;){
            if(k==-1||t[i] == t[k]){
                ++k;++i;
                nex[i]=k;
            }else k = nex[k];
    /*如果c[i]和c[k]中字符不同说明匹配是失败,要把k的值重新退到next[ k ]
    直到两者相同才停止。这样做的好处是没必要再重新从头再来,节约时间*/
        }
    }

    简单KMP算法的实现:

    //返回主串中匹配的位置(第一个),如果不匹配返回-1;
    int kmp(char *s,char *t,int lens,int lent)
    {
        int i = 0, j = 0;
        while(i < lens&&j<lent) {
            if(j==-1||s[i] == t[j]){
                i++;j++;
                if(j==lent){
                    return i-j+1;
                }
            }else j=nex[j];
        }
        return -1;
    }

    几道例题:

    洛谷P3375:

    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int maxn = 1e6 + 10;
    int nex[maxn];
    char s[maxn],t[maxn];
    int lens,lent;
    void get_next(){
        nex[0] = -1;
        for(int i = 0,k = -1;i < lent;){
            if(k==-1||t[i] == t[k]){
                ++k;++i;
                nex[i]=k;
            }else k = nex[k];
        }
    }
        
    void kmp()
    {
        int i = 0, j = 0;
        while(i < lens&&j<lent) {
            if(j==-1||s[i] == t[j]){
                i++;j++;
                if(j==lent){
                    printf("%d
    ",i-j+1);
                    j=nex[j];
                }
            }else j=nex[j];
        }
    }
    int main(){
        while(~scanf("%s %s",s,t)){
            lens=strlen(s);
            lent=strlen(t);
            get_next();
            kmp();
            for(int i=1;i<=lent;++i){
                printf("%d%c",nex[i],i==lent?'
    ':' ');
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    jquery on()动态绑定元素的的点击事件无反应的问题记录
    【分享】开源富文本编辑器之间的较量
    【分享】JS如何为复制的Web文本添加其他信息
    HTML table导出到Excel中的解决办法
    Vue跨门槛系列之实例的阐述
    Vue.js 基本功能了解一下~
    JS数据结构的栈和队列操作
    CSS宽度高度的百分比取值基于谁
    CSS个人笔记
    使用word设置标题级别, 自动生成和大纲对应的多级列表, 自动生成索引目录
  • 原文地址:https://www.cnblogs.com/Cwolf9/p/8921469.html
Copyright © 2011-2022 走看看