CF271D Good Substrings 哈希(模板)

原题:http://codeforces.com/contest/271/problem/D

题解:求满足要求的本质不同的个数。分别枚举左右端点,子段和判断是否不超过k个坏字母,通过hash来判断是否重复。

定义hash函数H(C)=\sum _{i=1}^m c_i*b^{m-i}

显然:H(C,k+1)=H(C,k)*b+c_{k+1}

从位置k+1到长度为n的子串:H(C,n+k)-H(C,k)*b^n

应用时用 无符号整形,自然溢出省去求模。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ull unsigned long long 
using namespace std;
const int N=2e3+10,Z=26,M=1e9+7;
char s[N],str[N];
int mark[N],sum[N],n,k,cnt; 
ull q[N*N];
int main(){
//	freopen("cf166d.in","r",stdin);
	scanf("%s%s",s+1,str);n=strlen(s+1);
	scanf("%d",&k);
	for(int i=1;i<=n;i++) if(str[s[i]-'a']=='0') sum[i]=1;
	for(int i=1;i<=n;i++) sum[i]+=sum[i-1];
	cnt=0;
	for(int i=1;i<=n;i++){
		ull hash=0;
		for(int j=i;j<=n;j++){
			if(sum[j]-sum[i-1]>k) break;
			hash=(hash*M+s[j]-'a'+1);
			q[cnt++]=hash;
		} 
	}
	sort(q,q+cnt);
	printf("%d\n",unique(q,q+cnt)-q);
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/weixin_39689721/article/details/87297336