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 }

 

posted @ 2020-07-24 10:26  programmer_w  阅读(160)  评论(0编辑  收藏  举报