zoukankan      html  css  js  c++  java
  • 学渣乱搞系列之扩展KMP的那点事

    扩展KMP牵涉了一些相对运动的姿势,比较费解!本学渣看了一天的扩展KMP,打算写点东西。。。本文看后,出现的后果本人一概不负责。毕竟我不是很会表达。

    扩展KMP是搞什么灰机的?本学渣所知道的扩展KMP是来解集训篇那道字符串题的。有了犯罪动机,现在就要下手。不要以为扩展KMP就以为与KMP关系暧昧。屁大点事,两个根本不是一个东西。只是有点思想是一致的,就是利用已经匹配的信息避免一些不必要的匹配。

    以此提高匹配速度。不过扩展KMP也能干KMP干的事。但是速度没KMP那么快。

    扩展KMP要造两个数组,一个Next数组,一个exd数组,前一个是存储模式串的后缀串的最长前缀长,exd数组就是我们的终极目标!我们的终极目标是干吗?泡妞把妹?AC?。。。。。。

    后缀造了造前缀?下面讲下如何求next吧,网上很多教程都是讲求exd的。假设s就是串t。

    Exd[i] = s[i….n]与t[1..m]的最大前缀长度。(i > = 0 && I < n)

    假设s[a…p] == t[0..p-a]表示a位置与模式串所能达到的最大前缀长度。

    那么我们有a <= k <= p 且 s[k…p]   ==   t[k-a…p-a]

    为什么啊?相对位置啊k – a = x – 0;    x = k-a;

    现在假设我们要求next[i]。  i > k ;

    还记得我们上一次匹配吗??那时候的s[a]是与t[0]对齐。现在我们利用的就是这次对齐。

    求next[i]就是要把t[0]与s[i]对齐。那么next[i-a]存的是什么呢?是不是s[a]与t[0]对齐时,

    S[i]是不是与t[i-a]对齐的呢?I – a = x – 0 ;  x = i-a;

    那么从next[i-a]记录的是什么东西呢?是不是表示t[i-a]与t[0]对齐时的最长前缀么?

    假设L  =  next[i-a]; 

    求的是next[i] 此时是把s[i]与t[0]对齐,前面有t[i-a]与t[0]的最大前缀,t[i-a]又正是上次对着s[i]的,所以L很有可能就是s[i]与t[0]对齐时的最长前缀。为什么是很有可能呢?

    设p = a + next[a]-1;  上次的匹配范围是多少来着?s[a,p] == t[0,p-a]  匹配i时,i+L-1很有可能超过p,超过的世界,那是我们没有匹配过的。所以要单独处理下。

    而i+L-1 < p 则一切尽在匹配之中,exd[i]就等于L,没有等于啊。。。。因为无法确定后面的是不是失配了。。。

    为什么不能再长呢?因为因为,t[i-a…p-a]只有L长的与t[0…p-a]匹配啊。。。

    为什么求出next[i],因为next[a]已经求出了,i-a<= i 求next[i]时,next[i-a]早已求出。。。。。

    好了,现在大家终于都不理解啥是扩展KMP了。欢迎各种乱评。。。

    show me your code?

     1 void exkmp(int *arr,char *s,char *t){
     2     int i,j,k,u,v;
     3     nxt[0] = strlen(t);
     4     for(i = 0; t[i+1] && t[i] == t[i+1]; i++);
     5     nxt[k = 1] = 1;
     6     for(i = 2; t[i]; i++){
     7         u = k+nxt[k];
     8         v = i+nxt[i-k];
     9         if(v < u) nxt[i] = nxt[i-k];
    10         else{
    11             for(j = u-i; t[i+j] && t[j] == t[i+j]; j++);
    12             nxt[k = i] = j;
    13         }
    14     }
    15     for(i = 0; s[i]&&t[i]&&s[i] == t[i]; i++);
    16     arr[k = 0] = i;
    17     for(i = 1; s[i]; i++){
    18         u = k+nxt[k];
    19         v = i+nxt[i-k];
    20         if(v < u) arr[i] = nxt[i-k];
    21         else{
    22             for(j = max(0,u-i);s[i+j]&&t[j]&&s[i+j] == t[j]; j++);
    23             arr[k = i] = j;
    24         }
    25     }
    26 }
    View Code
  • 相关阅读:
    思考
    创建Windows Mobile上兼容性好的UI 程序
    中文乱码(二)
    中文乱码(三)
    MySQL字符集产生乱码的简单讲解
    MySql乱码解决(五)
    中文乱码(四)
    mysql中文问题全处理
    Linux 中 x86 的内联汇编
    arm下的gcc内联汇编
  • 原文地址:https://www.cnblogs.com/crackpotisback/p/3876274.html
Copyright © 2011-2022 走看看