Stammering Aliens HDU - 4080
题意:每组数据为一个整数m和一个长度不小于m的字符串,求该字符串的一个子串,该子串在满足出现次数不小于m的同时应尽量长。
输出该长度和最右侧出现的起始位置。如果存在多组数据,输出有最靠近右侧的那组。(本题索引从0开始)
Sample Input
3 baaaababababbababbab 11 baaaababababbababbab 3 cccccc 0
Sample Output
5 12 none 4 2
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int inf = 0x3f3f3f3f; 4 typedef long long int ll; 5 typedef unsigned long long int ull; 6 const int maxn = 1e5 + 10; 7 ull hs[maxn]; 8 ull base[maxn]; 9 char str[maxn]; 10 int m; 11 int len; 12 ull gethash(int i, int j) {//获得子串的hash 13 return hs[j] - hs[i - 1] * base[j - i + 1]; 14 } 15 bool solve(int mid) {//二分长度 16 map<ull, int>mp; 17 for(int i=1;i<=len-mid+1;++i) { 18 ull A = gethash(i, i + mid - 1); 19 if (++mp[A] >= m)return true;//注意:如果使用mp[A]++;if(mp[A]>=m) 可能会超时。 20 } 21 return false; 22 } 23 int main() { 24 while (~scanf("%d", &m), m) { 25 scanf("%s", str + 1); 26 len = strlen(str + 1); 27 base[0] = 1; 28 hs[0] = 0; 29 for (int i = 1;i <= len;i++) 30 base[i] = base[i - 1] * 131, hs[i] = hs[i - 1] * 131 + (str[i] - 'a' + 1);//hash初始化 31 int ans = inf; 32 int l = 1, r = len + 1, mid; 33 while (r >= l) { 34 mid = l + r >> 1; 35 if (solve(mid))l = mid + 1, ans = mid; 36 else r = mid - 1; 37 } 38 if (ans == inf)puts("none"); 39 else { 40 int pos = 1; 41 map<ull, int>mp; 42 for(int i=1;i<=len-ans+1;++i) {//寻找最右边的位置,因为从左往右遍历所以最后得到的pos就是答案 43 ull A = gethash(i, i + ans - 1); 44 if (++mp[A] >= m) { 45 pos = i; 46 } 47 } 48 printf("%d %d\n", ans, pos - 1);//因为题目要求从0开始计数,所以pos要-1; 49 } 50 } 51 52 }