呃の,这题,真的不想说话。。
题目大意
给出N个由小写字母组成的字符串,统计至少在M个字符串中出现过的长度为L的字符串数
一看,就知道是哈希——
对于每个长度为L的串,都哈希一下——还要记得
推下一个哈希值,对于同一个模板中出现多次的字符串要记得去重
然后。。不要跟我说什么字符串哈希27进制更稳。。也不要说什么双大质数模数不会被卡。。反正我华丽丽地 了一片,40分!
拼了命凑了一下午,生无可恋。。只能抄标程模数+26进制。。
只想说, 绝对不是个好哈希模数!!!
PS:不想写哈希表,
水过。。
上“凄凄惨惨戚戚”的代码:
#pragma GCC optimize(6)
#include<cstdio>
#include<algorithm>
#define LL long long
using namespace std;
const LL P1=499999999999993,P2=999973,PP=26;
int n,m,L,ans,T[2005];char s[1005];LL pow[2][1005];
struct ff{
LL a,b;
bool operator <(const ff y)const{return a<y.a||(a==y.a&&b<y.b);}
bool operator ==(const ff y)const{return a==y.a&&b==y.b;}
void clear(){a=b=0;}
}now,hsh[1005],all[2000005];
char gt(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
int read(){
int ret=0;char ch=gt();
while(ch<'0'||ch>'9') ch=gt();
while(ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=gt();
return ret;
}
int main(){
n=read(),m=read(),L=read();
pow[0][0]=pow[1][0]=1;
for(int i=1;i<=L;i++) pow[0][i]=pow[0][i-1]*PP%P1,pow[1][i]=pow[1][i-1]*PP%P2; //在Mod意义下的预处理
for(int j=1;j<=n;j++){
char ch=gt();int len=0;
while(ch<'a'||ch>'z') ch=gt();
while(ch>='a'&&ch<='z') s[++len]=ch-'a',ch=gt();
if(len<L) continue;
now.clear();
for(int i=1;i<L;i++) now.a=(now.a*PP+s[i])%P1,now.b=(now.b*PP+s[i])%P2;
for(int i=L;i<=len;i++){
now.a=((now.a-pow[0][L-1]*s[i-L])%P1+P1)%P1,now.b=((now.b-pow[1][L-1]*s[i-L])%P2+P2)%P2;
now.a=(now.a*PP+s[i])%P1,now.b=(now.b*PP+s[i])%P2;
hsh[++T[j]]=now;
}
sort(hsh+1,hsh+1+T[j]),T[j]=unique(hsh+1,hsh+1+T[j])-hsh-1;
for(int i=1;i<=T[j];i++) all[++T[0]]=hsh[i];
}
sort(all+1,all+1+T[0]);
for(int i=1,j;i<=T[0];i=j){
j=i+1;
while(j<=T[0]&&all[j].a==all[i].a&&all[j].b==all[i].b) j++;
ans+=(j-i>=m);
}
printf("%d\n",ans);
return 0;
}