哈希 POI KOR-Beads

题意: 给出 n n n个数,可将它们分为连续的若干个串,每个串有 k k k个数(长度不足 k k k则丢弃),如串 ( 1 , 1 , 1 , 2 , 2 , 2 , 3 , 3 , 3 , 1 , 2 , 3 , 3 , 1 , 2 , 2 , 1 , 3 , 3 , 2 , 1 ) (1,1,1,2,2,2,3,3,3,1,2,3,3,1,2,2,1,3,3,2,1) (1,1,1,2,2,2,3,3,3,1,2,3,3,1,2,2,1,3,3,2,1),当 k = 2 k=2 k=2时,我们得到 6 6 6个不同的子串: ( 1 , 1 ) , ( 1 , 2 ) , ( 2 , 2 ) , ( 3 , 3 ) , ( 3 , 1 ) , ( 2 , 3 ) (1,1),(1,2),(2,2),(3,3),(3,1),(2,3) (1,1),(1,2),(2,2),(3,3),(3,1),(2,3)。 求使得不同的串最多的 k k k值及串的个数。串可翻转,即子串 1 , 2 , 3 1,2,3 1,2,3 3 , 2 , 1 3,2,1 3,2,1被认为是一样的。

我们预处理出前缀哈希和后缀哈希,这里我们自然溢出,对于枚举到的每一个k,我们求出每一段的前缀哈希和后缀哈希,然后将2者相乘用set判重。

#include<bits/stdc++.h>
#define ull unsigned long long
using namespace std;
const int c=2000001001;
int n,a[1001000],k;
ull hash1[1001000],mi[1001000],ans,res[1001000],maxn,hash2[1001000];
set<ull> s;
int main()
{
	mi[0]=1;
    cin>>n;
    for(int i=1;i<=n;++i)
        scanf("%d",&a[i]);
    for(int i=1;i<=n;++i)
    {
        hash1[i]=hash1[i-1]*c+a[i];//前缀哈希
        mi[i]=mi[i-1]*c;
    }	
    for(int i=n;i>=1;--i)
    	hash2[i]=hash2[i+1]*c+a[i];//后缀哈希
    for(int i=1;i<=n;++i)//枚举题目中的k
    {
    	if(n/i<maxn)//对于当前的k如果可以分成的段数小于已经求出的最大值
			break;
    	s.clear();
        k=0;
        for(int j=i;j<=n;j+=i)//枚举每一段
        {
            ull g1=hash1[j]-hash1[j-i]*mi[i];//这一段的前缀哈希
            ull g2=hash2[j-i+1]-hash2[j+1]*mi[i];//这一段的后缀哈希
            ull g3=g1*g2;//将2者相乘放入set里
            if(s.count(g3))
            	continue;
            s.insert(g3);
            k++;
        }
        if(k>maxn)
        {
            ans=1;
            maxn=k;
            res[ans]=i;
        }
        else if(k==maxn)
        {
            ans++;
            res[ans]=i;

        }
    }
    cout<<maxn<<" "<<ans<<endl;
    for(int i=1;i<=ans;++i)
        printf("%d ",res[i]);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值