当前位置: 代码迷 >> 综合 >> LA - 4513 - Stammering Aliens(Hash + 二分)
  详细解决方案

LA - 4513 - Stammering Aliens(Hash + 二分)

热度:86   发布时间:2024-01-10 13:10:27.0

题意:给一个整数m和一个字符串,求该字符串中至少出现m次的子串的最大长度及最后一个字串的位置(m >= 1, 字符串长度在m和40000之间)。

题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2514

——>>第一道hash解字符串,照LJ《训练指南》敲罢了。。。

#include <cstdio>
#include <cstring>
#include <algorithm>using namespace std;const int maxn = 40000 + 10;
const int x = 17;char s[maxn];
int n, m, pos;
int rak[maxn];
unsigned long long H[maxn], xp[maxn], hah[maxn];bool cmp(const int& a, const int& b) {return hah[a] < hah[b] || (hah[a] == hah[b] && a < b);
}void getH() {H[n] = 0;for(int i = n-1; i >= 0; i--) H[i] = H[i+1] * x + (s[i] - 'a');
}void getXp() {xp[0] = 1;for(int i = 1; i <= n; i++) xp[i] = xp[i-1] * x;
}bool possible(int L) {int cnt = 0;pos = -1;for(int i = 0; i <= n-L; i++) {rak[i] = i;hah[i] = H[i] - H[i+L] * xp[L];}sort(rak, rak + n - L + 1, cmp);for(int i = 0; i <= n-L; i++) {if(!i || hah[rak[i]] != hah[rak[i-1]]) cnt = 0;if(++cnt >= m) pos = max(pos, rak[i]);}return pos >= 0;
}void solve() {n = strlen(s);getH();getXp();if(!possible(1)) puts("none");else {int L = 1, R = n+1;while(R - L > 1) {int M = (L + R) >> 1;if(possible(M)) L = M;else R = M;}possible(L);printf("%d %d\n", L, pos);}
}int main()
{while(scanf("%d", &m) == 1 && m) {scanf("%s", s);solve();}return 0;
}