洛谷P4503 [CTSC2014]企鹅QQ
本题在CTSC中算简单的了 但是它仍然是CTSC啊
这题是我的第二道字符串hash,有一定难度
这题的主要难点:
1. 如何判断两个用户名是同一个人
题目中说:若两个账户名称是相似的,当且仅当这两个字符串等长且恰好只有一位不同
而题目中又说:为了简化你的工作,小Q给你的N 个字符串长度均等于L
这一波简直爽歪歪,我们只需要枚举每一个位置,把该字符串减去那一个字符的hash值算出来,然后暴力判断(下面讲)
2.如何计算答案
这个题目的第二个难点在于如何计算答案。由于一些字符串可能会两两相等,我们用一个temp来记录当前有几个字符串相等,当下一个字符串相等时,由于它和前面的都相等,所以ans+=temp
3.新手hash上路提醒
- 大质数玄学一点
听说搞个妹子生日啥的会rp++ - 字符串 hash时经常会预处理一波pow
- 字符串 hash时用unsigned long long(自动取模)
代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
const int p=31131;
unsigned long long a[30010],pow[210],hash[30010];
int N,L,S,temp,ans;
char s[30010][210];
int main()
{
scanf("%d%d%d",&N,&L,&S);
pow[0]=1;
for (int i=1;i<=210;i++)
pow[i]=pow[i-1]*p;
for (int i=1;i<=N;i++)
scanf("%s",s[i]+1);
for (int i=1;i<=N;i++){
for (int j=1;j<=L;j++){
hash[i]=hash[i]*p+s[i][j];
}
}
for (int k=1;k<=L;k++){
for (int i=1;i<=N;i++){
a[i]=hash[i]-pow[L-k]*s[i][k];
}
sort(a+1,a+N+1);
temp=0;
for (int i=2;i<=N;i++){
if (a[i]==a[i-1]){
temp++;
ans+=temp;
}
else temp=0;
}
}
printf("%d",ans);
return 0;
}