体验了一把字符串Hash的做法,感觉Hash这种人品算法好神奇。
也许这道题的正解是后缀数组,但Hash做法的优势就是编码复杂度大大降低。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int maxn = + ;
const int x = ;
int n, m, pos;
unsigned long long H[maxn], xp[maxn];
unsigned long long hash[maxn];
int rank[maxn];
char s[maxn]; bool cmp(const int& a, const int& b)
{ return hash[a] < hash[b] || (hash[a] == hash[b] && a < b); } bool possible(int L)
{
int cnt = ;
pos = -;
for(int i = ; i + L - < n; i++)
{
rank[i] = i;
hash[i] = H[i] - H[i + L] * xp[L];
}
sort(rank, rank + n - L + , cmp);
for(int i = ; i + L - < n; i++)
{
if(i == || hash[rank[i]] != hash[rank[i - ]]) cnt = ;
if(++cnt >= m) pos = max(pos, rank[i]);
}
return pos >= ;
} int main()
{
//freopen("in.txt", "r", stdin); xp[] = ;
for(int i = ; i < maxn; i++) xp[i] = xp[i - ] * x; while(scanf("%d", &m) == && m)
{
scanf("%s", s);
n = strlen(s);
H[n] = ;
for(int i = n - ; i >= ; i--) H[i] = H[i + ] * x + s[i] - 'a'; if(!possible()) puts("none");
else
{
int L = , R = n;
while(L < R)
{
int M = (L + R + ) / ;
if(possible(M)) L = M;
else R = M - ;
}
possible(L);
printf("%d %d\n", L, pos);
}
} return ;
}
代码君