首页 > 其他分享 >[笔记](例题更新中)Z函数(扩展KMP)

[笔记](例题更新中)Z函数(扩展KMP)

时间:2024-10-23 20:01:35浏览次数:1  
标签:匹配段 string int 笔记 数组 KMP 例题 函数

对于长度为\(n\)的字符串\(S\),定义\(z[i]\)表示\(S\)本身和\(S[i,n]\)这个后缀的最长公共前缀(LCP)的长度,(特别地,\(z[1]\)可以记为\(0\)或\(n\))则\(z\)被称为\(S\)的Z函数。

扩展KMP算法可以在\(O(n)\)的时间复杂度内求得\(S\)的Z函数数组。

约定:

  • 字符串下标从\(\bf{1}\)开始,下标从\(0\)开始的代码可以参见OI Wiki
  • 本文中\(z[1]=n\)。

正文

定义位置\(i\)的匹配段(也称作Z-box)为区间\([i,i+z[i]-1]\)。

设当前正在处理\(z[i]\),且\(z[1\sim (i-1)]\)均已经求出。我们设\([l,r]\)表示前\(i-1\)个匹配段中,右端点最大的一个,显然有\(l<i\)。

我们分类讨论\(i\)与\(r\)的位置关系。

  • \(i\le r\):则我们有\(S[i,r]=S[i-l+1,r-l+1]\),再考虑\((i-l+1)\)的匹配段长度\(z[i-l+1]\):
    • \(z[i-l+1]<(r-i+1)\):说明\(z[i]=z[i-l+1]\)。
    • \(z[i-l+1]\ge(r-i+1)\):令\(z[i]=r-i+1\),然后暴力向后匹配直到不能拓展为止。
  • \(i>r\):令\(z[i]=0\),然后然后暴力向后匹配直到不能拓展为止。
求$z$数组
void getz(int z[],string s,int n){
	z[1]=n;
	for(int i=2,l=0,r=0;i<=n;i++){
		if(i<=r&&z[i-l+1]<r-i+1) z[i]=z[i-l+1];
		else{//将1.2和2.合并为一条
			z[i]=max(0ll,r-i+1);
			while(i+z[i]<=n&&s[z[i]+1]==s[i+z[i]]) z[i]++;
			if(i+z[i]-1>r) l=i,r=i+z[i]-1;
		}
	}
}

时间复杂度的证明和KMP类似,外层for循环执行\(n\)次,内层while循环每执行一次\(r\)都会往右移动\(1\)位,故内层循环总执行次数最多是\(n\)。于是总时间复杂度为\(O(n)\)。

例题

P5410 【模板】扩展 KMP/exKMP(Z 函数)

这道题除了需要求\(B\)的Z函数数组,还需要求\(A\)每个后缀和\(B\)的最长公共前缀,这样就相当于在\(2\)个字符串之间跑Z函数。设我们处理的数组是\(p\),在\(B\)的Z数组已经求出的前提下,当前处理到\(p[i]\),和\(p[1\sim(i-1)]\)均已求出。我们设\([l,r]\)表示前\(i-1\)个匹配段中,右端点最大的一个,显然有\(l<i\)。仍然分类讨论\(i\)与\(r\)的位置关系。

  • \(i\le r\):则我们有\(B[i,r]=B[i-l+1,r-l+1]\),再考虑\((i-l+1)\)的匹配段长度\(z[i-l+1]\):
    • \(z[i-l+1]<(r-i+1)\):说明\(p[i]=z[i-l+1]\)。
    • \(z[i-l+1]\ge(r-i+1)\):令\(p[i]=r-i+1\),然后暴力向后匹配直到不能拓展为止。
  • \(i>r\):令\(p[i]=0\),然后然后暴力向后匹配直到不能拓展为止。

注意循环要从\(1\)开始。

求$p$数组
void ext(int p[],string a,string b,int n){
	for(int i=1,l=0,r=0;i<=n;i++){
		if(i<=r&&z[i-l+1]<r-i+1) p[i]=z[i-l+1];
		else{
			p[i]=max(0ll,r-i+1);
			while(i+p[i]<=n&&a[i+p[i]]==b[p[i]+1]) p[i]++;
			if(i+p[i]-1>r) l=i,r=i+p[i]-1;
		}
	}
}
全代码
#include<bits/stdc++.h>
#define int long long 
#define N 20000010
using namespace std;
string a,b;
int z[N],p[N];
void getz(int z[],string s,int n){
	z[1]=n;
	for(int i=2,l=0,r=0;i<=n;i++){
		if(i<=r&&z[i-l+1]<r-i+1) z[i]=z[i-l+1];
		else{
			z[i]=max(0ll,r-i+1);
			while(i+z[i]<=n&&s[z[i]+1]==s[i+z[i]]) z[i]++;
			if(i+z[i]-1>r) l=i,r=i+z[i]-1;
		}
	}
}
void ext(int p[],string a,string b,int n){
	for(int i=1,l=0,r=0;i<=n;i++){
		if(i<=r&&z[i-l+1]<r-i+1) p[i]=z[i-l+1];
		else{
			p[i]=max(0ll,r-i+1);
			while(i+p[i]<=n&&a[i+p[i]]==b[p[i]+1]) p[i]++;
			if(i+p[i]-1>r) l=i,r=i+p[i]-1;
		}
	}
}
signed main(){
	int n,m;
	cin>>a>>b;
	n=a.size(),m=b.size(),a=' '+a,b=' '+b;
	getz(z,b,m);
	ext(p,a,b,n);
	int ans=0;
	for(int i=1;i<=m;i++) ans^=(i*(z[i]+1));
	cout<<ans<<"\n";
	ans=0;
	for(int i=1;i<=n;i++) ans^=(i*(p[i]+1));
	cout<<ans<<"\n";
	return 0;
}

\(- TO BE CONTINUED -\)

标签:匹配段,string,int,笔记,数组,KMP,例题,函数
From: https://www.cnblogs.com/Sinktank/p/18496178

相关文章

  • Vue学习笔记(一)
    模板语法Vue使用一种基于HTML的模板语法,使我们能够声明式地将其组件实例的数据绑定到呈现的DOM上。所有的Vue模板都是语法层面合法的HTML,可以被符合规范的浏览器和HTML解析器解析。文本差值最基本的数据绑定形式是文本插值,它使用的是“Mustache”语法(即双大括号):<scrip......
  • [MySQL笔记]窗口函数
    什么是窗口函数窗口函数(WindowFunction),又被叫做分析函数(AnalyticsFunction)。窗口函数允许用户在不显式分组查询的情况下对结果集进行分组和聚合计算。窗口函数能够为结果集中的每一行计算类似排名、行号、百分比和移动聚合函数等值。窗口函数原则上只能写在select子句中......
  • 【算法笔记】前缀和算法原理深度剖析(超全详细版)
    【算法笔记】前缀和算法原理深度剖析(超全详细版)......
  • 七月在线公开课笔记-六-
    七月在线公开课笔记(六)【七月在线】机器学习就业训练营16期-P12:在线直播:3-图像与文本基础_ev-IT自学网100-BV1Z9T5ewEKL呃各位同学大家晚上好,然后我们今天呢就给大家讲解,我们的文本和图像基础啊,嗯这个呢就是很多同学比较关心,因为我们现在很多的一个呃岗位呢,上网工程师的岗......
  • 七月在线公开课笔记-九-
    七月在线公开课笔记(九)【七月在线】机器学习就业训练营16期-P8:在线直播:8-XGBoost精讲_ev-IT自学网100-BV1Z9T5ewEKL嗯如果没有问题的话,我们就准备开始好吧,额按照咱们这个课程安排啊,今天呢我们要介绍的是超级boost模型呃,这个模型呢其实我们从第一次上课的时候,就介绍到了这......
  • 七月在线公开课笔记-二十一-
    七月在线公开课笔记(二十一)人工智能—推荐系统公开课(七月在线出品)-P16:快速入门推荐系统串讲-七月在线-julyedu-BV1Ry4y127CV今天跟大家分享的是深入浅出推荐系统啊,然后我们会围绕着推荐系统,它的核心内容呃,想召回排序重排,这些核心模块进行展开介绍,那首先做下自我介绍。我......
  • 七月在线公开课笔记-二十五-
    七月在线公开课笔记(二十五)人工智能—机器学习公开课(七月在线出品)-P11:机器学习项目实施方法论-七月在线-julyedu-BV1W5411n7fgOkay。嗯,时间应该到了哈,那这样的话我们就正式开始好吗?没有问题的话,我们就开始,好吧。啊,是这样,这个非常高兴啊能够有机会呃。......
  • 七月在线公开课笔记-二十四-
    七月在线公开课笔记(二十四)人工智能—机器学习中的数学(七月在线出品)-P18:随机梯度下降法的困难与变种-七月在线-julyedu-BV1Vo4y1o7t1我们稍微再简介一下我后面这个部分的内容,这部分当然可能更深入一些。大家我们去年有一个公开公开课,就专门讲这个大家也可以找一找叫做这个......
  • 七月在线公开课笔记-二十三-
    七月在线公开课笔记(二十三)人工智能—机器学习中的数学(七月在线出品)-P1:Taylor展式与拟牛顿-七月在线-julyedu-BV1Vo4y1o7t1这次我们探讨它的展示与它的相关应用,如米牛顿。我们首先给出塔的展示的本身的,它的定义,它的展示的公式的本身。然后我们利用它来计算某一些函数的近似......
  • 七月在线公开课笔记-二十七-
    七月在线公开课笔记(二十七)人工智能—机器学习公开课(七月在线出品)-P25:【公开课】数据挖掘与机器学习基础-七月在线-julyedu-BV1W5411n7fg可以是吧?好,那么我们稍等一下啊,稍等一下我们。在8点钟我们就准时开始我们的一个直播的内容。对。那么各位同学之前有过这个积极学习和深......