POJ3261-哈希

这个题让求至少出现K次的最大长度的子串,属于最大化最小值问题,首先应该想到二分求字串的长度,二分的过程是O(logN)的,注意judge的时候怎样判断是否满足情况以及满足情况后l,r的变化。可以给每一个子串定一个hash值,判断所有hash值中相同的是否超过K个,hash方法同BDKshash。。POJ数据略水。。a[i]的值远远没有到100W。。poj的字符串题一直感觉数据都不太好。。红着脸水过。。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 using namespace std;
 5 const int maxn = 20010;
 6 typedef long long ll;
 7 
 8 int n,k,seed = 131;
 9 ll base[maxn];
10 ll one[maxn],hash[maxn];
11 int a[maxn];
12 
13 bool judge(int x)
14 {
15 
16     for(int i = 1; i <= n-x+1; ++i)
17     {
18         hash[i] = one[i+x-1]-one[i-1]*base[x];
19     }
20     int j = n-x+1;
21     sort(hash+1,hash+1+j);
22     int sum = 1;
23     for(int i = 1; i <= n-x+1; ++i)
24     {
25         if(hash[i] == hash[i+1]) sum++;
26         else{
27             if(sum >= k) return true;
28             else sum = 1;
29         }
30     }
31     if(sum >= k) return true;
32     else return false;
33 }
34 
35 int main()
36 {
37     scanf("%d%d",&n,&k);
38     base[0] = 1;
39     for(int i = 1; i <= n; ++i) base[i] = base[i-1]*seed;
40     for(int i = 1; i <= n; ++i)
41         scanf("%d",a+i);
42     one[0] = 0;
43     for(int i = 1; i <= n; i++)
44         one[i] = one[i-1]*seed+a[i];
45     int l = 1,r = n,mid,ans;
46     while(l <= r)
47     {
48         int mid = l +(r-l)/2;
49         if(judge(mid)) l = mid+1,ans = mid;
50         else r = mid-1;
51     }
52     printf("%d\n",ans);
53 }

 

posted @ 2015-08-20 15:21  Norlan  阅读(436)  评论(0编辑  收藏  举报