字符串(哈希,前缀和后缀的应用)

洛谷 p4503【企鹅QQ】[CTSC2014] 企鹅 QQ - 洛谷

这道题主要运用了前缀和后缀的思想。

因为没有相同的字符串,所以要找出相似的字符串,就是去掉一个位置,这个位置前后分别哈希,前后哈希相加和如果相等,那么这两个字符串必然是相似的。

#include<cstring>
#include<algorithm>
using namespace std;
typedef unsigned long long ull;
const int maxn=30010;
/*
一开始打max会一直报错,所以没用这个。
这个要与常用单词区分开,以免概念模糊。
*/
ull hs1[30010][233], hs2[30010][233], hs[30010];
char ch[30010][233];
int n, l, s;
 inline void line(int x) {//inline 在这里用处不大,可不打
	for (int i = 1; i <= l; i++) {
		hs1[x][i] = hs1[x][i - 1] * 131 + ch[x][i];//计算前缀
	}
	for (int i = l; i >= 1; i--) {
		hs2[x][i] = hs2[x][i + 1] * 233 + ch[x][i];//计算后缀
	}
}
int main(){
	
	scanf("%d%d%d", &n, &l, &s);
	for (int i = 1; i <= n; i++) {
		scanf("%s", ch[i] + 1);  //细节加1
		line(i);
	}
	int ans = 1, Ans = 0;
	for (int i = 1; i <= l; i++) {
		for (int j = 1; j <= n; j++) {
			hs[j] = hs1[j][i - 1] * 237 + hs2[j][i + 1]*211;//计算去掉i点之外的从1到n的哈希值
			//237,211可以替换任意较大质数(如果某几个数据过不了),这里乘也是多一层保险
		}
		sort(hs + 1, hs + 1 + n);
		//把哈希值相同的排在一起
		for (int j = 1; j< n; j++) { //此处注意小于,别打等于,虽然问题不大
			if (hs[j] == hs[j + 1]) Ans += ans, ans++;
			//如果有k个点哈希值都相同,那么把这k个点看做节点,多一个点就会多出k个相似,然后节点数加1
			else  ans = 1;
			//如果不同,节点置1;
		}
	}
	printf("%d\n", Ans);
	return 0;
}

  • 10
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值