计蒜客T3103-特殊关系

本文介绍了一种通过哈希方法解决字符串匹配问题的算法。针对特定格式的字符串组,利用26进制哈希实现快速查找具有特殊关系的字符串组,并提供了一个C++示例程序。

题目描述:
蒜头君有很多组字符串形如 {x,y}x,y, xx 的长度不确定,而 yy 的长度是 22。
如果有两组字符串 a , ba,b,例如 a =a= {“ABCD”,“CC”} 和 b =b= {“CCAAAA”,“AB”} ,aa 组的第二个字符串是 bb 组第一个字符串的开头,而 bb 组的第二个字符串是 aa 组第一个字符串的开头。这是一个非常有趣的现象,蒜头君会认为这两组字符串 a,ba,b 存在一种特殊关系。
但是蒜头君又觉得例如 a =a= {“ABAB”,“AB”}, b =b= {“ABAC”,“AB”} 这样两组字符串是没有特殊关系的,因为它们的第二个字符串相同。
现在蒜头君有 NN 组字符串,他想要知道这些字符串中有多少组存在特殊关系。

输入格式
第一行输入一个整数 NN,表示有 NN 组字符串;
接下来 NN 行,每行输入两个字符串 x,yx,y(均为大写字母)。
注意:有可能有多个城市叫一样的名字,但是它们肯定不属于同一个省。
注意可能存在相同的 xx 字符串,但保证对于相同的 xx 所对应的字符串 yy 一定不同

输出格式
输出这些字符串中有多少组存在特殊关系。

数据范围
对于 100% 的数据,1≤N≤200000,2≤∣x∣,∣y∣≤10,输入保证所有字符串都由大写字母构成

样例输入
5
JISUANKE SU
SUANKE JI
JISUAN SU
JISK SK
SKSK SK

样例输出
2

在练习的时候卡了很久,脑子不好使不知道怎么用map来存储。本题y固定为2,可以直接采用4位26进制的hash,直接将字符串a的前两位与字符串b连接起来,然后hash维护两个数组,一个数组h1表示原来的数,另一个数组h2用来表示翻转后的数,将两者的乘积相加,最后除以2输出即为答案。

#include<iostream>
#include<cstring>
#include<map>
#include<cstdio>
using namespace std;
#define mp make_pair
const int maxn=2e5+5;
int n;
int h1[26*26*26*27], h2[26*26*26*27];
char s1[20],s2[20];
int main()
{
	scanf("%d",&n);
	for(int i = 0; i < n; i++){
		scanf("%s %s",s1,s2);
		if(s1[0] != s2[0] || s1[1] != s2[1]){
			int x1 = (((s1[0] - 'A') * 26 + s1[1] - 'A') * 26 + (s2[0] - 'A')) * 26 + s2[1] - 'A';
			int x2 = (((s2[0] - 'A') * 26 + s2[1] - 'A') * 26 + (s1[0] - 'A')) * 26 + s1[1] - 'A';
			h1[x1]++;
			h2[x2]++;
		}
	}
	long long ans = 0;
	for(int i = 0; i < 26 * 26 * 26 * 27; i++){
		ans += h1[i] * h2[i];
	}
	cout << ans / 2 << endl;
	return 0;
}


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值