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;
    	}
    
  • 相关阅读:
    Windows Server 2008 R2 免费使用 7200天 激活
    ceph部署步骤
    for循环间隔修改(解决把以空格隔开需要把一整行作为整体)
    my_learn
    fiddler-抓包
    基础软件搭建
    【原创】一层Nginx反向代理K8S化部署实践
    【原创】K8S使用ceph-csi持久化存储之CephFS
    【原创】K8S使用ceph-csi持久化存储之RBD
    [原创]自动化部署K8S(v1.10.11)集群
  • 原文地址:https://www.cnblogs.com/little-uu/p/14449844.html
Copyright © 2011-2022 走看看