体验了一把字符串Hash的做法,感觉Hash这种人品算法好神奇。
也许这道题的正解是后缀数组,但Hash做法的优势就是编码复杂度大大降低。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 6 const int maxn = 40000 + 10; 7 const int x = 123; 8 int n, m, pos; 9 unsigned long long H[maxn], xp[maxn]; 10 unsigned long long hash[maxn]; 11 int rank[maxn]; 12 char s[maxn]; 13 14 bool cmp(const int& a, const int& b) 15 { return hash[a] < hash[b] || (hash[a] == hash[b] && a < b); } 16 17 bool possible(int L) 18 { 19 int cnt = 0; 20 pos = -1; 21 for(int i = 0; i + L - 1 < n; i++) 22 { 23 rank[i] = i; 24 hash[i] = H[i] - H[i + L] * xp[L]; 25 } 26 sort(rank, rank + n - L + 1, cmp); 27 for(int i = 0; i + L - 1 < n; i++) 28 { 29 if(i == 0 || hash[rank[i]] != hash[rank[i - 1]]) cnt = 0; 30 if(++cnt >= m) pos = max(pos, rank[i]); 31 } 32 return pos >= 0; 33 } 34 35 int main() 36 { 37 //freopen("in.txt", "r", stdin); 38 39 xp[0] = 1; 40 for(int i = 1; i < maxn; i++) xp[i] = xp[i - 1] * x; 41 42 while(scanf("%d", &m) == 1 && m) 43 { 44 scanf("%s", s); 45 n = strlen(s); 46 H[n] = 0; 47 for(int i = n - 1; i >= 0; i--) H[i] = H[i + 1] * x + s[i] - 'a'; 48 49 if(!possible(1)) puts("none"); 50 else 51 { 52 int L = 1, R = n; 53 while(L < R) 54 { 55 int M = (L + R + 1) / 2; 56 if(possible(M)) L = M; 57 else R = M - 1; 58 } 59 possible(L); 60 printf("%d %d ", L, pos); 61 } 62 } 63 64 return 0; 65 }