zoukankan      html  css  js  c++  java
  • KMP总结

    通俗描述

    当在B中匹配A时,若在某一位失配,我们需要知道至少要将A往后移多少位才能确保之前匹配的内容仍然匹配(不然匹配肯定无效),而这个偏移量可以由“当前位置A的前缀中,A的非前缀后缀与A的前缀的最大匹配长度”计算出,考虑到在B中的计算过程实际上在计算“B的后缀与A的前缀的最大匹配长度”,两者可以用相似的做法求出,而非前缀性质可由初始化时的错位保证。

    基本定义

    • A:模板串,下标1~n
    • B:文本串,下标1~m
    • nxt[i] = max{ j | j<i 且 A[i-j+1~i] = A[1~j] }
    • f[i] = max{ j | j <= i 且 j <= n 且 B[i-j+1~i] = A[1~j] }
    • nxt[i]的“候选项”:{ j | j<i 且 A[i-j+1~i] = A[1~j] }

    相关性质

    引理1

    若j是nxt[i]的候选项,则j-1必是nxt[i-1]的候选项。

    引理2

    (j_0)是nxt[i]的一个候选项,则nxt[i]的小于(j_0)的最大的候选项是nxt[(j_0)]。
    证:反证法,若有$ nxt[j_0] le j_1 le j_0 (,)j_1(是nxt[i]的候选项。 ) ecause j_1(是nxt[i]的候选项 ) herefore $ A[1~(j_1)] = A[i-(j_1)+1~i]
    $ ecause j_0(是nxt[i]的候选项 ) herefore $ A[1~(j_0)] = A[i-(j_0)+1~i],即A[(j_0 - j_1 +1) ~ (j_0)] = A[$ i-j_1+1$~ (i) ]
    $ herefore $ A[1 ~ (j_1)] = A[(j_0-j_1+1) ~ (j_0)]
    $ herefore $ nxt[(j_0)]应为(j_1)
    $ herefore $ 矛盾
    即得证。

    计算方法

    由引理1和引理2,计算nxt[i]时,只要考虑nxt[i-1]+1,nxt[nxt[i-1]]+1,...亦可理解成“A错一位后匹配它自己”

    nxt求法

    nxt[1]=0;
    for(int i=2,j=0;i<=n;i++)
    {
        whiel(j>0&&a[i]!=a[j+1]) j=nxt[j];
        if(a[i]==a[j+1]) j++;
        nxt[i]=j;
    }
    

    f求法

    for(int i=1,j=0;i<=m;i++)
    {
        while(j&&(j==n||b[i]!=a[j+1])) j=nxt[j];
        if(b[i]==a[j+1]) j++;
        f[i]=j;
        if(f[i]==n) { ... }
    }
    

    nxt数组的意义

    1. 自身定义:nxt[i] = max{ j | j<i 且 A[i-j+1~i] = A[1~j] }
    2. 可将整个KMP视为一个自动机,nxt数组即为“失配边”

    常见用处

    1. 单文本单模板字符串匹配
    2. 求字符串最小循环元长度(如果有,即为n-nxt[n])
  • 相关阅读:
    前端页面的防抖与节流
    vue3.0 响应式原理
    cssBEM命名规范及常用CSS class 命名
    vue2.x 响应式原理
    npm 相关命令
    Node之 fs
    Node 之 Buffer
    Node之path
    Node之process
    Node.js 如何处理 ES6 模块
  • 原文地址:https://www.cnblogs.com/happyZYM/p/11379686.html
Copyright © 2011-2022 走看看