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;
    }
    
    

    学长的代码。镇楼。

  • 相关阅读:
    SqlServer查询优化方法
    关于导入excel问题
    修改SQL数据库中表字段类型时,报“一个或多个对象访问此列”错误的解决方法
    软件架构之我见
    算法-插入排序
    算法-快速排序
    WCF系列 Restful WCF
    WCF系列 基础概念
    cocos2dx-是男人就坚持20s 练手项目
    nodejs 聊天室简单实现
  • 原文地址:https://www.cnblogs.com/skyleafcoder/p/12319561.html
Copyright © 2011-2022 走看看