【bzoj2081】[Poi2010]Beads Hash

题目描述

Zxl有一次决定制造一条项链,她以非常便宜的价格买了一长条鲜艳的珊瑚珠子,她现在也有一个机器,能把这条珠子切成很多块(子串),每块有k(k>0)个珠子,如果这条珠子的长度不是k的倍数,最后一块小于k的就不要拉(nc真浪费),保证珠子的长度为正整数。 Zxl喜欢多样的项链,为她应该怎样选择数字k来尽可能得到更多的不同的子串感到好奇,子串都是可以反转的,换句话说,子串(1,2,3)和(3,2,1)是一样的。写一个程序,为Zxl决定最适合的k从而获得最多不同的子串。 例如:这一串珠子是: (1,1,1,2,2,2,3,3,3,1,2,3,3,1,2,2,1,3,3,2,1), k=1的时候,我们得到3个不同的子串: (1),(2),(3) k=2的时候,我们得到6个不同的子串: (1,1),(1,2),(2,2),(3,3),(3,1),(2,3) k=3的时候,我们得到5个不同的子串: (1,1,1),(2,2,2),(3,3,3),(1,2,3),(3,1,2) k=4的时候,我们得到5个不同的子串: (1,1,1,2),(2,2,3,3),(3,1,2,3),(3,1,2,2),(1,3,3,2)

输入

共有两行,第一行一个整数n代表珠子的长度,(n<=200000),第二行是由空格分开的颜色ai(1<=ai<=n)。

输出

也有两行,第一行两个整数,第一个整数代表能获得的最大不同的子串个数,第二个整数代表能获得最大值的k的个数,第二行输出所有的k(中间有空格)。

样例输入

21
1 1 1 2 2 2 3 3 3 1 2 3 3 1 2 2 1 3 3 2 1

样例输出

6 1



题解

Hash

处理不同字符串问题,Hash是个好方法。

然而这道题要求反过来的字符串与原串算作同一种,所以Hash值也应相同。

一种比较简单且容易实现的方法是把它们正反做两次Hash,然后把它们乘起来作为新的Hash值,因为乘法满足交换率。

这里为了防止被卡取了两个底数进行Hash。

最终使用map判断就行了。

时间复杂度为$O(n\log n*\log n)=O(n\log^2n)$

#include <cstdio>
#include <map>
#define N 200010
using namespace std;
typedef unsigned long long ull;
struct data
{
	ull b[N] , h1[N] , h2[N];
	ull hash(int l , int r)
	{
		return (h1[r] - h1[l - 1] * b[r - l + 1]) * (h2[l] - h2[r + 1] * b[r - l + 1]);
	}
}t1 , t2;
map<pair<ull , ull> , bool> f;
int a[N] , sta[N] , top;
int main()
{
	int n , i , j , cnt , ans = 0;
	scanf("%d" , &n);
	t1.b[0] = t2.b[0] = 1;
	for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &a[i]);
	for(i = 1 ; i <= n ; i ++ ) t1.b[i] = t1.b[i - 1] * 233 , t2.b[i] = t2.b[i - 1] * 2333;
	for(i = 1 ; i <= n ; i ++ ) t1.h1[i] = t1.h1[i - 1] * 233 + a[i] , t2.h1[i] = t2.h1[i - 1] * 2333 + a[i];
	for(i = n ; i >= 1 ; i -- ) t1.h2[i] = t1.h2[i + 1] * 233 + a[i] , t2.h2[i] = t2.h2[i + 1] * 2333 + a[i];
	for(i = 1 ; i <= n ; i ++ )
	{
		f.clear() , cnt = 0;
		for(j = 1 ; j + i - 1 <= n ; j += i)
			if(!f[make_pair(t1.hash(j , j + i - 1) , t2.hash(j , j + i - 1))])
				f[make_pair(t1.hash(j , j + i - 1) , t2.hash(j , j + i - 1))] = 1 , cnt ++ ;
		if(cnt > ans) top = 1 , sta[top] = i , ans = cnt;
		else if(cnt == ans) sta[++top] = i;
	}
	printf("%d %d\n" , ans , top);
	for(i = 1 ; i < top ; i ++ ) printf("%d " , sta[i]);
	printf("%d" , sta[top]);
	return 0;
}
时间: 2024-08-05 11:18:37

【bzoj2081】[Poi2010]Beads Hash的相关文章

【BZOJ2085】[Poi2010]Hamsters hash+倍增floyd

[BZOJ2085][Poi2010]Hamsters Description Tz养了一群仓鼠,他们都有英文小写的名字,现在Tz想用一个字母序列来表示他们的名字,只要他们的名字是字母序列中的一个子串就算,出现多次可以重复计算.现在Tz想好了要出现多少个名字,请你求出最短的字母序列的长度是多少. Input 输入:第一行n(1<=n<=200)和m(1<=m<=10的9此方),n表示有多少个仓鼠,m表示Tz希望出现名字的次数,接下来n行,每行都是仓鼠的名字(中间没有空格). Out

【BZOJ2096】[Poi2010]Pilots 双指针+单调队列

[BZOJ2096][Poi2010]Pilots Description Tz又耍畸形了!!他要当飞行员,他拿到了一个飞行员测试难度序列,他设定了一个难度差的最大值,在序列中他想找到一个最长的子串,任意两个难度差不会超过他设定的最大值.耍畸形一个人是不行的,于是他找到了你. Input 输入:第一行两个有空格隔开的整数k(0<=k<=2000,000,000),n(1<=n<=3000,000),k代表Tz设定的最大值,n代表难度序列的长度.第二行为n个由空格隔开的整数ai(1&

【转】各种字符串Hash函数比较

常用的字符串Hash函数还有ELFHash,APHash等等,都是十分简单有效的方法.这些函数使用位运算使得每一个字符都对最后的函数值产生影响.另外还有以MD5和SHA1为代表的杂凑函数,这些函数几乎不可能找到碰撞. 常用字符串哈希函数有BKDRHash,APHash,DJBHash,JSHash,RSHash,SDBMHash,PJWHash,ELFHash等等.对于以上几种哈希函数,我对其进行了一个小小的评测. Hash函数 数据1 数据2 数据3 数据4 数据1得分 数据2得分 数据3得分

【BZOJ2095】[Poi2010]Bridges 动态加边网络流

[BZOJ2095][Poi2010]Bridges Description YYD为了减肥,他来到了瘦海,这是一个巨大的海,海中有n个小岛,小岛之间有m座桥连接,两个小岛之间不会有两座桥,并且从一个小岛可以到另外任意一个小岛.现在YYD想骑单车从小岛1出发,骑过每一座桥,到达每一个小岛,然后回到小岛1.霸中同学为了让YYD减肥成功,召唤了大风,由于是海上,风变得十分大,经过每一座桥都有不可避免的风阻碍YYD,YYD十分ddt,于是用泡芙贿赂了你,希望你能帮他找出一条承受的最大风力最小的路线.

【BZOJ1125】[POI2008]Poc hash+map+SBT

[BZOJ1125][POI2008]Poc Description n列火车,每条有l节车厢.每节车厢有一种颜色(用小写字母表示).有m次车厢交换操作.求:对于每列火车,在交换车厢的某个时刻,与其颜色完全相同的火车最多有多少. Input n l m (2 ≤ n ≤ 1000, 1 ≤ l ≤ 100, 0 ≤ m ≤ 100000) n行字符串,长度为l m行,每行4个数a b c d,a车的第b个字符与c车第d个字符交换. Output n个数,在交换车厢的某个时刻,与该车颜色完全相同的

【BZOJ2081】【Poi2010(17th)】Beads RKhash+hash表 请记住这个神一样的数:200019

链接: #include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/45743869"); } 题解: 枚举串长,数据范围20W. 然后串长为 i 时需要枚举 ?ni? 次. 加一起是 O(nlogn) 我们把每个串hash一下就好了. 然后自然溢出就好了,,,. 我无限WA啊..最后wyfcyx给我提

【BZOJ2081】Beads(哈希表)

题意: 翻转是指其中一段长度为k的子串全部翻转 n<=200000 a[i]<=n 思路:枚举k,直接哈希判充即可 时间复杂度是n/i求和,根据定理可得是O(n log n)级别的 单哈双哈都可能被卡,我用的是单哈+哈希表判重 1 const mo=250109; 2 var h1,h2,mi,c,a,head,vet,next:array[0..1000000]of longint; 3 n,i,p,j,st,ed,t1,t2,t3,l,ans,tot:longint; 4 5 functi

【转载】对一致性Hash算法,Java代码实现的深入研究

原文地址:http://www.cnblogs.com/xrq730/p/5186728.html 一致性Hash算法 关于一致性Hash算法,在我之前的博文中已经有多次提到了,MemCache超详细解读一文中"一致性Hash算法"部分,对于为什么要使用一致性Hash算法.一致性Hash算法的算法原理做了详细的解读. 算法的具体原理这里再次贴上: 先构造一个长度为232的整数环(这个环被称为一致性Hash环),根据节点名称的Hash值(其分布为[0, 232-1])将服务器节点放置在这

【转】哈希(Hash)与加密(Encrypt)的基本原理、区别及工程应用

0.摘要 今天看到吉日嘎拉的一篇关于管理软件中信息加密和安全的文章,感觉非常有实际意义.文中作者从实践经验出发,讨论了信息管理软件中如何通过哈希和加密进行数据保护.但是从文章评论中也可以看出很多朋友对这个方面一些基本概念比较模糊,这样就容易“照葫芦画瓢”,不能根据自身具体情况灵活选择和使用各种哈希和加密方式.本文不对哈希和加密做过于深入的讨论,而是对哈希和加密的基本概念和原理进行阐述.比较,并结合具体实践说明如何选择哈希和加密算法.如何提高安全性等问题,使朋友们做到“知其然,知其所以然”,这样就