【题解】Codeforces 471D. MUH and Cube Walls 差分KMP

给定两个整数序列 A , B ( 2 e 5 ) A,B(2e5) ,求 B B 的差分序列在 A A 的差分序列中的出现次数.


首先如果 B B 的长度是 1 1 ,答案就是 A A 的长度。

否则做差分,然后整数KMP.

题目一点不难,但是写了几次都有问题,很多问题都在于,KMP算法很多地方都用了字符串结尾是\0这个性质,但是整数KMP是不能这样的。

重新总结一套鲁棒性强的板子。需要注意的是if之后新的前缀函数值不一定是j,因为如果j=w,会被缩减一次。

	for(int i=1, j=0; i<w; ++i)
	{
		while(j && pat[i]!=pat[j]) j=fail[j-1];
		fail[i] = pat[i]==pat[j] ? ++j : 0;
	}

	int ans = 0;
	for(int i=0, j=0; i<n; ++i)
	{
		while(j && tex[i]!=pat[j]) j=fail[j-1];
		if(tex[i]==pat[j] && ++j==w) ++ans, j=fail[j-1];
	}
	printf("%d\n",ans );

完整代码

/* LittleFall : Hello! */
#include <bits/stdc++.h>
using namespace std; using ll = long long; inline int read();
const int M = 200016, MOD = 1000000007;

int tex[M], pat[M], fail[M];
int main(void)
{
	#ifdef _LITTLEFALL_
	freopen("in.txt","r",stdin);
    #endif

	int n = read(), w = read();
	if(w==1)
	{
		printf("%d\n",n );
		return 0;
	}
	for(int i=0; i<n; ++i) tex[i] = read();
	for(int i=0; i<w; ++i) pat[i] = read();

	n--, w--;
	for(int i=0; i<n; ++i) tex[i] = tex[i+1] - tex[i];//printf("%d",tex[i] );printf("\n");
	for(int i=0; i<w; ++i) pat[i] = pat[i+1] - pat[i];//printf("%d",pat[i] );printf("\n");
	tex[n] = pat[w] = 0;

	for(int i=1, j=0; i<w; ++i)
	{
		while(j && pat[i]!=pat[j]) j=fail[j-1];
		fail[i] = pat[i]==pat[j] ? ++j : 0;
	}

	int ans = 0;
	for(int i=0, j=0; i<n; ++i)
	{
		while(j && tex[i]!=pat[j]) j=fail[j-1];
		if(tex[i]==pat[j] && ++j==w) ++ans, j=fail[j-1];
	}
	printf("%d\n",ans );


    return 0;
}


inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
发布了375 篇原创文章 · 获赞 305 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/m0_37809890/article/details/103048190