• 扩展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;
    	}
    
  • 相关阅读:
    代码校验工具 SublimeLinter 的安装与使用
    java中写sql语句的小小细节
    搭建Hexo博客并部署到Github
    更改npm全局模块和cache默认安装位置
    笔记本连接老式显示器(VGA线+HDMI接口)
    用JSON-server模拟REST API
    使用 Feed43
    Coding.net+Myeclipse 2014 Git配置
    line-height 属性
    border-style 属性
  • 原文地址:https://www.cnblogs.com/little-uu/p/14449844.html
Copyright © 2020-2023  润新知