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 想知道,在给定的 \(n\) 个账户名称中,有多少对是相似的。
为了简化你的工作,小Q给你的N 个字符串长度均等于L ,且只包含大小写字母、数字、下划线以及‘@’共64种字符,而且不存在两个相同的账户名称。
输入格式
第一行包含三个正整数 \(N,L,S\)。其中 \(N\) 表示账户名称数量,\(L\) 表示账户名称长度,\(S\) 用来表示字符集规模大小,它的值只可能为 \(2\) 或 \(64\)。
若 \(S\) 等于 \(2\),账户名称中只包含字符 0 和 1 共 \(2\) 种字符;
若 \(S\) 等于 \(64\),账户名称中可能包含大小写字母、数字、下划线以及 @ 共 \(64\) 种字符。
随后 \(N\) 行,每行一个长度为 \(L\) 的字符串,用来描述一个账户名称。数据保证 \(N\) 个字符串是两两不同的。
输出格式
仅一行一个正整数,表示共有多少对相似的账户名称。
$ N \leq 30000,L\leq200$
题意复述:
给你一些长度相等且互不相同的字符串,定两个字符串相似的条件为两字符串中有且仅有一位不同,求这些字符串中相似字符串的对数
Solution :
比较好想的哈希题,但是对我这个对哈希不熟的蒟蒻来说还是硬控了我半小时就是了。
首先我们给每个字符串的每一位定一个哈希值:
\(c[i][j]*131^j\) 然后整个字符串的哈希值就是将每一位的哈希值XOR到一起,这样做的好处就是我们在删掉这个字符串中的某个字符时,可以直接将原串的hash与被删除位的hashXOR一下,非常的省时省力
然后这题的做法就呼之欲出了,首先给每一位和每一个字符串求出Hash值,然后枚举每一位,将其删除,将删完之后的字符串排序,对于每种相等的字符串(Hash值相同),设其个数为cnt,则该部分的答案显然就是\((cnt-1)*cnt/2\)
然后这题就做完了
话说最后的答案统计貌似不用排序也行,可以开一个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;
}

浙公网安备 33010602011771号