P4503 [CTSC2014] 企鹅 QQ
P4503 [CTSC2014] 企鹅 QQ
[CTSC2014] 企鹅 QQ
题目背景
PenguinQQ 是中国最大、最具影响力的 SNS(Social Networking Services)网站,以实名制为基础,为用户提供日志、群、即时通讯、相册、集市等丰富强大的互联网功能体验,满足用户对社交、资讯、娱乐、交易等多方面的需求。
题目描述
小 Q 是 PenguinQQ 网站的管理员,他最近在进行一项有趣的研究——哪些账户是同一个人注册的。经过长时间的分析,小Q发现同一个人注册的账户名称总是很相似的,例如 Penguin1,Penguin2,Penguin3……于是小 Q 决定先对这种相似的情形进行统计。
小 Q 定义,若两个账户名称是相似的,当且仅当这两个字符串等长且恰好只有一位不同。例如“Penguin1”和“Penguin2”是相似的,但“Penguin1”和“2Penguin”不是相似的。而小 Q 想知道,在给定的
为了简化你的工作,小Q给你的N 个字符串长度均等于L ,且只包含大小写字母、数字、下划线以及‘@’共64种字符,而且不存在两个相同的账户名称。
输入格式
第一行包含三个正整数
若 0
和 1
共
若 @
共
随后
输出格式
仅一行一个正整数,表示共有多少对相似的账户名称。
题意复述:
给你一些长度相等且互不相同的字符串,定两个字符串相似的条件为两字符串中有且仅有一位不同,求这些字符串中相似字符串的对数
Solution :
比较好想的哈希题,但是对我这个对哈希不熟的蒟蒻来说还是硬控了我半小时就是了。
首先我们给每个字符串的每一位定一个哈希值:
然后这题的做法就呼之欲出了,首先给每一位和每一个字符串求出Hash值,然后枚举每一位,将其删除,将删完之后的字符串排序,对于每种相等的字符串(Hash值相同),设其个数为cnt,则该部分的答案显然就是
然后这题就做完了
话说最后的答案统计貌似不用排序也行,可以开一个Map,时间复杂度貌似是稳定的单log?但是由于我没学过用函数清空map,也不想手打清空,所以我还是选择相信快排不会创亖我
Code:
#include <bits/stdc++.h> typedef unsigned long long ull; const int N=30005; const int Len=205; using namespace std; char c[N][Len]; ull hsh[N][Len],val[N]; int n,m,k; long long ans; void Hash(int k) { for(int i=1;i<=n;i++) { val[i]=hsh[i][m]^hsh[i][k]; } sort(val+1,val+1+n); } void work() { cin>>n>>m>>k; for(int i=1;i<=n;i++) { scanf("%s",c[i]); hsh[i][m+1]=1; hsh[i][m]=0; for(int j=m-1;j>=0;j--) { hsh[i][j]=c[i][j]*hsh[i][m+1]; hsh[i][m+1]*=131; } for(int j=0;j<m;j++) { hsh[i][m]^=hsh[i][j]; } } for(int i=0;i<m;i++) { Hash(i); int last=0; for(int j=1;j<=n+1;j++) { if(val[last]!=val[j]) { int cnt=j-last; ans+=(cnt-1)*cnt/2; last=j; } } } printf("%lld",ans); } int main() { //freopen("qq.in","r",stdin); //freopen("qq.out","w",stdout); work(); return 0; }