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

    最近新学的三个算法,一直都没写博客,后缀自动机和线性基还有一点小尾巴,争取这两天结束

    一、应用场景

    (T)串与(S)串的每个后缀的最长公共前缀

    二、算法流程

    图片来源

    1. 假设当前遍历到S串位置i,即nxtS[0]...nxtS[i - 1]这i个位置的值已经计算得到。设置两个变量,st和pos。pos代表以st为起始位置的字符匹配成功的最右边界,也就是"pos = 最后一个匹配成功位置"。相较于字符串T得出,S[st...pos]等于T[0...pos-st]。

    2. 再定义一个辅助数组int nxtT[],其中nxtT[i]含义为:T[i]...T[m - 1]与T的最长相同前缀长度

    1. 根据第一条得出:S[i]对应T[i - st],S[i...pos] = T[i - st...pos - st],同时我们已经知道T[i - st...]与T的最长公共前缀,而T[i - st...pos - st]的最长公共前缀一定比它小,所以如果i + nxtT[i - st] < pos,说明最长公共前缀在我已知的范围内,根据nxtT数组的定义,此时nxtS[i] = nxtT[i - st]。

    1. 如果i + next[i - st] == pos呢?S[pos+1] != T[pos - st + 1]且T[pos - i + 1] != T[pos - st + 1],但S[pos]有可能等于T[pos - i + 1],所以我们可以直接从S[pos + 1]与T[pos - i + 1]开始往后匹配,加快了速度。

    1. 如果i + nxtT[i - st] > pos呢?那说明S[i...pos]与T[i-st...pos-st]相同,注意到S[pos + 1] != T[pos - st + 1]且T[pos - i + 1] == T[pos - st + 1],也就是说S[pos + 1] != T[pos - i + 1],所以就没有继续往下判断的必要了,我们可以直接将nxtS[i]赋值为pos - i + 1。

    明天更……

    三、代码

    1. 第一次扩展
        for (int i = 0;S[i] == T[i]&&i < lenT&&i < lenS;i++) pos++,nextS[0]++;
    
    1. 4和5两条可以合并
     if (nextT[i-st] >= pos-i+1){
                int j = max(pos-i+1,0);
                while(S[i+j] == T[j]&&i+j < lenS&&j < lenT) j++;
                nextS[i] = j,st = i;
     }
    
    1. 第3条
    else nextS[i] = nextT[i-st];
    

    完整代码:因为我需要先求一个nxtT,所以需要调用两边函数

            for (int i = 2,l = 1,r = 1;i <= lenb;i++){
    		if (i <= r&&kmpA[i-l+1] < r-i+1) kmpA[i] = kmpA[i-l+1];
    		else{
    			kmpA[i] = max(0,r-i+1);
    			while (i+kmpA[i] <= lenb&&b[kmpA[i]+1] == b[i+kmpA[i]]) ++kmpA[i];
    		}
    		if (i+kmpA[i]-1 > r) l = i,r = i+kmpA[i]-1;
    	}
    	for (int i = 1,l = 0,r = 0;i <= lena;i++){
    		if (i <= r&&kmpA[i-l+1] < r-i+1) kmpB[i] = kmpA[i-l+1];
    		else{
    			kmpB[i] = max(0,r-i+1);
    			while (i+kmpB[i] <= lena&&b[kmpB[i]+1] == a[i+kmpB[i]]) ++kmpB[i];
    		}
    		if (i+kmpB[i]-1 > r) l = i,r = i+kmpB[i]-1;
    	}
    
  • 相关阅读:
    Redission 中 RPermitExpirableSemaphore 用法
    Linux查询CPU核数
    Http超时时间之SocketTimeout
    In Theano, how to do Reverse-MaxPooling in the Convolutional MaxPooling Auto-Encoder
    如何让Ubuntu中virtualbox虚拟机用上USB设备
    Deep Learning Stuffs(持续更新中……)
    实例描述如何用python组件ctypes调用c的dll中的函数
    放弃MATLAB!简述winpython为什么比MATLAB更方便
    虚拟机Ubuntu10.04无法显示windows中文目录和文件
    W: GPG 错误
  • 原文地址:https://www.cnblogs.com/little-uu/p/14449844.html
Copyright © 2011-2022 走看看