zoukankan      html  css  js  c++  java
  • KMP

    作用是找大串里匹配的小串的位置

    理解好难,先讲一下原理。找目前字符串的Border:是一个字符串最长的,能跟真后缀相同的真前缀的长度。

    比如ABCDABCD

    从1号到八号 Border分别是00001234.。

    如何求Border:

    我们以ABABAC为例

    用肉眼明显知道

    001230

    我们知道如果前面的字符串对称,只需要把当前字符和前面字符对称总数+1比较,如果继续对称,那么对称总数+1,否则

    我们回到F[前一个总对称数]+1,这个字符比较,如果相等,下次比较则比较这个字符串的下一个即刻,如果依然不等,继续上述操作直到起点。

    感觉没讲得很清楚,看了一位大佬的博客,理解了一点,结合学长的代码,模拟了一下。

    https://blog.csdn.net/u011564456/article/details/20862555

    大佬链接。

    求出了Border.。我们需要利用Border进行优化匹配。

    还是刚才那个道理,匹配字符看Boeder,即看是否有无效的匹配。

    ABCBABCAAB

    ABCAA

    匹配到第4个就无法匹配了,我们此时可以利用Boeder,直接移动三位而不是一位。

    从而产生优化的效果。

    例如:

    学长的例子

    P=ABCDABD

    T=ABCABCDABABCDABCDABDE

    T的第一个位置开始匹配

     

    123456789012345678901

    ABCABCDABABCDABCDABDE

    ABCDABD

    1234567

     

    P的第4个字符匹配失败!

    我们到此成功匹配到了P3个字符,而F[3]=0

    - 所以也无法在??T_2, ?? T_3处继续产生匹配;

    P串向右移动k-F[k]=3个字符

     

    123456789012345678901

    ABCABCDABABCDABCDABDE

    ABCDABD

    1234567

    我们到此成功匹配到了P3个字符,而F[3]=0

    - 所以也无法在??T_2, ?? T_3处继续产生匹配;

    P串向右移动k-F[k]=3个字符

     

    123456789012345678901

    ABCABCDABABCDABCDABDE

                           ABCDABD

     1234567

    此时我们需要移动4而不是6.

    我们可以知道F[6]=2;

    即移动k-F[k]=4;

     

     

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=1000050;
    int F[maxn];
    char P[maxn],T[maxn];
    void getF(char *P,int m) {
        F[1]=0;
        for(int i = 2; i <= m; ++i) {
            int k=F[i-1];
            while(k&&P[k+1]!=P[i]) k=F[k];
            if(P[k+1]==P[i]) ++k;
            F[i]=k;
        }
    }
    void getMatch(char *P,int m,char *T,int n)
    {
        getF(P,m);
        int k=0;
        for(int i = 1; i <= n; ++i) {
            while(k&&T[i]!=P[k+1]) k=F[k];
            if(T[i]==P[k+1]) ++k;
            if(k==m) {
                printf("matched at %d
    ", i-m+1);
                k=F[k];
            }
        }
    }
    int main() {
        scanf("%s%s", T+1,P+1);
        getMatch(P,strlen(P+1),T,strlen(T+1));
        return 0;
    }
    
    

    学长的代码。镇楼。

  • 相关阅读:
    HDU 1102 Constructing Roads
    HDU 1285 确定比赛名次。
    最小生成树 HDU 各种畅通工程的题,prim和kru的模板题
    HDU Jungle Roads 1301 最小生成树、
    并查集小结(转)
    HDU hdu 2094 产生冠军 拓扑排序 判定环
    模运算(转)
    拓扑排序(主要是确定环和加法) HDU 2647 Reward
    HDU 1372 Knight Moves 简单BFS
    用计算机模型浅析人与人之间沟通方式 (一)如何谈话
  • 原文地址:https://www.cnblogs.com/skyleafcoder/p/12319561.html
Copyright © 2011-2022 走看看