Z-box / Z-algorithm字符串匹配

简介

z[i]:对于i这个位置和原本的字符串的相同前缀长度是多少

p[] +"#" + s[]——可知对于匹配串 文本串每个位置与其相同的前缀

z数组的处理

z[0]无效 = 0,用z[k](k < i)来推出z[i]

看看之前算好的z有没有可以覆盖当前的i,而且覆盖右边界越右越好   l,r是box的边界

if(没有之前的zbox能覆盖) 只好从i这一位暴力枚举处理答案

else if(has) s[i]能被覆盖 那么s[i]必然出现在是s[0~z[j] - 1]这一段 j指的是覆盖得住当前i的最大右边界的开头

好的,那么我们现在就去寻找这个s[i]在原串中的映射的位置,即i - l

此时显然,在box范围内的s[i~r]和映射的s[i-l ~ r-l] is same. 这一段的长度是L = r - i + 1

不难看出situation分为两种:

1.z[i - l] < L 直接可以得出 z[i] = z[i - l]

2.超出的部分只好暴力枚举找到边界

模板

//LEN——文本串 len——匹配串

void getz(){
	int l = 0,r = 0;
	z[0] = 0;
	for(int i = 1;i <= LEN + len; i++){
		if(i > r){
			int n = 0;
			while(p[n] == p[i + n]) n++;
			if(n){
				l = i;
				r = i + n - 1;
			}
			z[i] = n;
		}
		else{
			if(z[i - l] < r - i + 1) z[i] = z[i - l];
			else{
				int n = 1;
				while(p[r - i + n] == p[r + n]) n++;
				r = r + n - 1;
				l = i;
				z[i] = r - l + 1;
			}
		}
	}
}
发布了31 篇原创文章 · 获赞 5 · 访问量 1365

猜你喜欢

转载自blog.csdn.net/qq_43685900/article/details/103147798
z