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 }