【后缀数组】 HDOJ 2459 && POJ 3693 Maximum repetition substring

来源:互联网 发布:模拟人生4编程秘籍 编辑:程序博客网 时间:2024/04/30 16:35

这道题在后缀数组的那篇神论文中讲的很详细。。。。

#include <iostream>  #include <sstream>  #include <algorithm>  #include <vector>  #include <queue>  #include <stack>  #include <map>  #include <set>  #include <bitset>  #include <cstdio>  #include <cstring>  #include <cstdlib>  #include <cmath>  #include <climits>  #define maxn 100005#define eps 1e-6 #define mod 10007 #define INF 99999999  #define lowbit(x) (x&(-x))  //#define lson o<<1, L, mid  //#define rson o<<1 | 1, mid+1, R  typedef long long LL;using namespace std;char s[maxn];int sa[maxn], t[maxn], t2[maxn], c[maxn];void build(int n, int m){int i, *x = t, *y = t2, k, p;for(i = 0; i < m; i++) c[i] = 0;for(i = 0; i < n; i++) c[x[i] = s[i]]++;for(i = 1; i < m; i++) c[i] += c[i-1];for(i = n-1; i >= 0; i--) sa[--c[x[i]]] = i;for(k = 1; k <= n; k<<=1) {p = 0;for(i = n-k; i < n; i++) y[p++] = i;for(i = 0; i < n; i++) if(sa[i] >= k) y[p++] = sa[i] - k;for(i = 0; i < m; i++) c[i] = 0;for(i = 0; i < n; i++) c[x[y[i]]]++;for(i = 1; i < m; i++) c[i] += c[i-1];for(i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];swap(x, y), p = 1, x[sa[0]] = 0;for(i = 1; i < n; i++)x[sa[i]] = y[sa[i]] == y[sa[i-1]] && y[sa[i]+k] == y[sa[i-1]+k] ? p-1 : p++;if(p >= n) break;m = p;}}int rank[maxn], height[maxn];void getheight(int n){int i, j, k = 0;for(i = 0; i <= n; i++) rank[sa[i]] = i;for(i = 0; i < n; i++) {if(k) k--;j = sa[rank[i]-1];while(s[i+k] == s[j+k]) k++;height[rank[i]] = k;}}int dp[maxn][20];int a[maxn];void work(int n){int i, j;for(i = 1; i <= n; i++) dp[i][0] = height[i];for(j = 1; (1<<j) <= n; j++)for(i = 1; i+(1<<j)-1 <= n; i++)dp[i][j] = min(dp[i][j-1], dp[i+(1<<(j-1))][j-1]);}int query(int a, int b){int L = rank[a], R = rank[b];if(L > R) swap(L, R);L++;int k = 0;while((1<<(k+1)) <= R-L+1) k++;return min(dp[L][k], dp[R-(1<<k)+1][k]);}void debug(void){printf("%d\n", query(2, 4));}int main(void){int n, i, p, m, tmp, back, ans, cnt, res, j, _ = 0;while(scanf("%s", s)!=EOF) {if(s[0] == '#') break;n = strlen(s);build(n+1, 128);getheight(n);work(n);cnt = ans = 0;for(p = 1; p <= n; p++) {for(i = 0; i+p < n; i += p) {m = query(i, i+p);tmp = m/p+1;back = i-(p-m%p);if(back >= 0 && query(back, back+p) >= (p-m%p))tmp++;if(tmp > ans) {ans = tmp;cnt = 0;a[cnt++] = p;}else if(tmp == ans)a[cnt++] = p;}}res = -1, p = 1;for(i = 1; i <= n && res == -1; i++) {for(j = 0; j < cnt; j++) {p = a[j];if(query(sa[i], sa[i]+p) >= p*(ans-1)) {res = sa[i];break;}}}s[res+p*ans] = '\0';printf("Case %d: %s\n", ++_, s+res);}return 0;}


0 0
原创粉丝点击