【hash】珍珠

【来源】

https://loj.ac/problem/2427

【参考博客】

LOJ#2427. 「POI2010」珍珠项链 Beads

【题解】:

复杂度计算:

暴力枚举k每次计算是n/2+n/3+n/4+...+1的,用调和级数算是𝑂(𝑛𝑙𝑜𝑔𝑛)

头尾给hash一遍,然后存放到set里面去重。

所以就是O(nlog n logn )

 

【代码】:

 1 #include<set>
 2 #include<cstdio>
 3 #include<algorithm>
 4 
 5 const int N = 2e5+100;
 6 using namespace std;
 7 
 8 typedef unsigned long long ULL ;
 9 
10 ULL h1[N],h2[N],p[N],base=13331;
11 set<ULL> S ;
12 int str[N],Ans[N],cnt,n,res,t;
13 
14 void Get_Hash(){
15     p[0] = 1 ;
16     for(int i=1;i<=n;i++) {
17         p[i] = p[i - 1] * base ;
18         h1[i] = h1[i-1] * base + str[i] ;
19     }
20     for(int i=n;i>=1;i--){
21         h2[i] = h2[i+1] * base + str[i] ;
22     }
23 }
24 
25 int calc1(int L,int R ){
26     return h1[R] - h1[L-1] * p[R-L+1] ;
27 }
28 int calc2(int L,int R ){
29     return h2[L] - h2[R+1] * p[R-L+1] ;
30 }
31 
32 int Solve( int x ){
33     S.clear() ;
34     ULL tmp  ;
35     for(int i=1;i+x-1<=n;i+=x){
36         tmp = min( calc1(i,i+x-1) , calc2(i,i+x-1) );
37         S.insert(tmp);
38     }
39     return (int)S.size();
40 }
41 int main()
42 {
43     scanf("%d",&n);
44     for( int i = 1 ; i<=n ; i++ )   scanf("%llu",&str[i]);
45     Get_Hash() ;
46     for(int i=1;i<=n;i++){
47          t = Solve(i);
48          if( t > res ){
49             res = t ;
50             cnt = 0;
51          }
52          if( t == res ){
53              Ans[cnt++] = i ;
54          }
55     }
56     printf("%d %d\n",res,cnt);
57     for(int i=0;i<cnt;i++){
58         printf("%d%c",Ans[i],i==cnt-1?'\n':' ');
59     }
60     return 0 ;
61 
62 }
View Code

 

posted @ 2019-08-09 02:07  Osea  阅读(177)  评论(0编辑  收藏  举报