zoukankan      html  css  js  c++  java
  • 扩展KMP

    给定串S和T,求S的每一个后缀和T的最长公共前缀。

    方法1:暴力算法,时间复杂度O(n^2);

    方法2:后缀数组,利用height的性质可以求出该问题,时间复杂度为O(n),但是预处理为O(nlogn)

    方法3:扩展KMP,充分利用已经匹配过的性质,降低匹配的时间,时间复杂度为O(n)

    学习资料:http://www.docin.com/p-423302546.html

    设next[i]为这样一个数组,next[i]为串T的suffix(i)和suffix(0)的相似度,假设next[0-->k-1]已经算出了,并且在以前的匹配中,

    匹配到的最远处为p,如图 

    假设是suffix(a)和suffix(0)匹配到最远处p,那么有T[a-->p] == T[0-->p-a+1]那么这个匹配的后面一段也相等,即T[k-->p]==T[k-a-->p-a+1],

    又因为next[k-a]是已知的,令L = next[k-a]

    有两种情况,

    ①k+L-1 < p, 那么next[k] = L,不可能大于L,否则next[k-a] 就不等于L了, 可能有人会想到,为什么表示k+L-1<=p,这个因为,如果取等号,那么p+1的部分没被判断过,所以不能直接next[k] = L;

    ②K+L-1>=p, 那么要重新匹配超过p的部分,即T[p+1] 和T[p-k+1]重新匹配。

    九度oj 1535

     1 /*next[i] 表示T[i-->n]和T[0-->n]的相似度
     2 */
     3 
     4 #include <stdio.h>
     5 #include <string.h>
     6 const int N = 1000000 + 10;
     7 char S[N],T[N];
     8 int next[N];
     9 int extend[N];
    10 void makeNext()
    11 {
    12     int n,a,j,k,L,p;
    13     next[0] = n = strlen(T);
    14     a = 0;
    15     while(a+1<n && T[a]==T[a+1]) a++;
    16     next[1] = a;
    17     a = 1;
    18     for(k=2; k<n; ++k)
    19     {
    20         p = a + next[a] - 1;
    21         L = next[k-a];
    22         if(k+L-1>=p)
    23         {
    24             //这一切都要求p>=k,否则,从新从0开始匹配。
    25             j = p - k + 1 > 0 ? p-k+1 : 0;
    26             while(k+j<n && T[k+j]==T[j]) ++j;
    27             next[k] = j;
    28             a = k;
    29         }
    30         else
    31             next[k] = L;
    32 
    33     }
    34 
    35 }
    36 void makeExtend()
    37 {
    38     int sLen = strlen(S),tLen = strlen(T);
    39     int len = sLen < tLen ? sLen : tLen;
    40     int a = 0,k,j,L,p;
    41     while(a<len && S[a]==T[a]) a++;
    42     extend[0] = a;
    43     a = 0;
    44     for(k=1; k<sLen; ++k)
    45     {
    46         p = a + extend[a] -1;
    47         L = next[k-a];
    48         if(k+L-1>=p)
    49         {
    50             j = p-k+1>0?p-k+1:0;
    51             while(k+j<sLen&&j<tLen &&S[k+j]==T[j])
    52                 j++;
    53             extend[k] = j;
    54             a = k;
    55         }
    56         else
    57             extend[k] = L;
    58     }
    59 }
    60 int main()
    61 {
    62     while(scanf("%s%s",S,T)!=EOF)
    63     {
    64         makeNext();
    65         makeExtend();
    66         int n = strlen(S);
    67         int ans = 0;
    68         for(int i=0; i<n; ++i)
    69             if(extend[i] == n - i)
    70             {
    71                 ans = extend[i];
    72                 break;
    73             }
    74         printf("%d
    ",ans);
    75     }
    76     return 0;
    77 }
  • 相关阅读:
    MySQL视图——学习笔记及实验
    小学生四则运算自动刷题库优化升级
    软件工程小项目——小学生四则运算自动刷题库
    笔记--运算符、表达式和语句
    笔记--基本数据类型与数组
    笔记--java入门
    原因: java.lang.ClassNotFoundException: Hello
    使用gopm代替go get 解决go包卡慢的问题
    调用微信截图功能c# 截图带扩展名
    如何用golang搜索抓取淘宝商品
  • 原文地址:https://www.cnblogs.com/justPassBy/p/4089619.html
Copyright © 2011-2022 走看看