zoukankan      html  css  js  c++  java
  • 「字符串匹配」学习笔记

    KMP

    单模式串匹配问题,复杂度$O(n+m)$

    思想:充分利用历史信息

    (以下图片画了一个小时,版权所有qaq)

    (鉴于C++字符串从0开始标号的缘故,以下数组下标从0开始)

    匹配

    匹配时,$i$指针指向文本串当前位,$j$指针指向模式串当前位

    如果当前位的文本串与模式串匹配成功,即$T_i = P_j$,两指针同时移动至下一位。

    如果当前位文本串与模式串失配,即$T_i eq P_j$。失配位置之前部分两串都是相同的。我们不移动文本串。当文本串不动而移动模式串时,实际上就是在前面的相同部分里,模式串前缀与文本串后缀匹配的过程。我们要找到模式串在移动过程中,第一个在$i$之前与文本串全部匹配的位置(可能是空),这样才好继续匹配。这等价于模式串$[0,j)$的最长相同前后缀。

    当模式串指针指向$len_p$时,意味着已经找到位置能够让模式串与文本串全部匹配。此时应该与处理方法应当与失配一样,向右移动找到第一个在$i$之前匹配的位置,也就是$j=nxt_j$。

    我们注意到整个算法的过程中$i$指针是不会往回移动的,这保证了算法的复杂度。KMP算法通过处理最长相同前后缀,减少了冗余匹配次数。注意,前缀和后缀是可以有重叠部分的。然而前后缀不能同时是原串自己,这样就没有意义了。

    在学习KMP匹配的过程中,要时常与暴力$O(nm)$做法作比较,得知KMP的正确性。我们使用$nxt_j$跳过一部分匹配,是因为这部分连在$i$之前的部分都不能匹配,必定不用考虑后面的内容。只有当$i$之前匹配,做下去才是有意义的。

    $nxt[]$的求解过程

    定义:$nxt_i$表示区间$[0,i)$中最长相同前后缀的长度。等价于模式串在$i$位置失配时,应该移动至$nxt_i$处。

    求解$nxt_i$时,要利用$nxt_{0~i-1}$的信息。

    边界条件:$nxt_0 = -1$

    如果$p_{nxt_{i-1}}=p_{i-1}$,利用之前的最长相同前后缀,加上这一位,得到一个最长相同前后缀。

    然而如果不相等呢?退而求其次,继续往前迭代,直到找到一个相等的位置为止。

    直到找到第一位。这是一个边界条件,我们比较第一位和$i-1$。

    进行到这一步说明最长相同前后缀的长度为0。

    AC自动机

    多模式串匹配问题,复杂度$O(n+m cdot L)$

    思想:就是KMP。一句话,失配时在所有模式串的前缀里,寻找当前已匹配部分的最长后缀。

    由于模式串可能有前后缀关系,匹配成功后需要一直跳$fail$统计。

    有一个优化,可以在匹配时不需跳$fail$边(注意是匹配时,不是匹配成功后,成功后如果要优化需要$fail$树)。就是让所有不存在的空儿子点成为$fail$的传送门。这样的AC自动机成为$Trie$图。

  • 相关阅读:
    UIView添加手势
    UIView常见属性设置汇总
    关于页面传值
    有关segue的简介
    alloc
    如何定义静态方法
    一座小城
    清明
    开通博客
    iOS学习之界面间传值
  • 原文地址:https://www.cnblogs.com/qixingzhi/p/11007446.html
Copyright © 2011-2022 走看看