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 }
  • 相关阅读:
    C. Shaass and Lights 解析(思維、組合)
    D. Binary String To Subsequences(队列)(贪心)
    CodeForces 1384B2. Koa and the Beach (Hard Version)(贪心)
    CodeForces 1384B1. Koa and the Beach (Easy Version)(搜索)
    CodeForces 1384C. String Transformation 1(贪心)(并查集)
    CodeForces 1384A. Common Prefixes
    POJ-2516 Minimum Cost(最小费用最大流)
    POJ3261-Milk Patterns(后缀数组)
    HDU-1300 Pearls(斜率DP)
    HDU-4528 小明系列故事-捉迷藏(BFS)
  • 原文地址:https://www.cnblogs.com/justPassBy/p/4089619.html
Copyright © 2011-2022 走看看