hdu 5008 Boring String Problem 【后缀数组】
2014-11-04 21:41
399 查看
后缀自动机有些时候还是没有后缀数组好用,注意输出0 0 的时候还要让l和r变成0
#pragma comment(linker, "/STACK:102400000,102400000") #include<iostream> #include<vector> #include<algorithm> #include<cstdio> #include<queue> #include<stack> #include<string> #include<map> #include<set> #include<cmath> #include<cassert> #include<cstring> #include<iomanip> using namespace std; #ifdef _WIN32 #define i64 __int64 #define out64 "%I64d\len" #define in64 "%I64d" #else #define i64 long long #define out64 "%lld\len" #define in64 "%lld" #endif /************ for topcoder by zz1215 *******************/ #define foreach(c,itr) for(__typeof((c).begin()) itr=(c).begin();itr!=(c).end();itr++) #define FOR(i,a,b) for( int i = (a) ; i <= (b) ; i ++) #define FF(i,a) for( int i = 0 ; i < (a) ; i ++) #define FFD(i,a,b) for( int i = (a) ; i >= (b) ; i --) #define S64(a) scanf(in64,&a) #define SS(a) scanf("%d",&a) #define LL(a) ((a)<<1) #define RR(a) (((a)<<1)+1) #define pb push_back #define pf push_front #define X first #define Y second #define CL(Q) while(!Q.empty())Q.pop() #define MM(name,what) memset(name,what,sizeof(name)) #define MC(a,b) memcpy(a,b,sizeof(b)) #define MAX(a,b) ((a)>(b)?(a):(b)) #define MIN(a,b) ((a)<(b)?(a):(b)) #define read freopen("out.txt","r",stdin) #define write freopen("out2.txt","w",stdout) const int inf = 0x3f3f3f3f; const i64 inf64 = 0x3f3f3f3f3f3f3f3fLL; const double oo = 10e9; const double eps = 10e-6; const double pi = acos(-1.0); const int maxn = 101234; char c[maxn]; int sa[maxn]; // 1~len 有效 int rk[maxn]; // 0~len-1 有效 int height[maxn]; // 2~len 有效 int wa[maxn], wb[maxn], wc[maxn], wd[maxn]; int cmp(int *r, int a, int b, int l){ return r[a] == r[b] && r[a + l] == r[b + l]; } void da(char *r, int *sa, int len, int maxc){ r[len++] = 0; int i, j, p, *x = wa, *y = wb, *t; for (i = 0; i<maxc; i++) wd[i] = 0; for (i = 0; i<len; i++) wd[x[i] = r[i]]++; for (i = 1; i<maxc; i++) wd[i] += wd[i - 1]; for (i = len - 1; i >= 0; i--) sa[--wd[x[i]]] = i; for (j = 1, p = 1; p<len; j *= 2, maxc = p) { for (p = 0, i = len - j; i<len; i++) y[p++] = i; for (i = 0; i<len; i++) if (sa[i] >= j) y[p++] = sa[i] - j; for (i = 0; i<len; i++) wc[i] = x[y[i]]; for (i = 0; i<maxc; i++) wd[i] = 0; for (i = 0; i<len; i++) wd[wc[i]]++; for (i = 1; i<maxc; i++) wd[i] += wd[i - 1]; for (i = len - 1; i >= 0; i--) sa[--wd[wc[i]]] = y[i]; for (t = x, x = y, y = t, p = 1, x[sa[0]] = 0, i = 1; i < len; i++){ x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? p - 1 : p++; } } return; } void get_height(char *r, int *sa, int len){ int i, j, k = 0; for (i = 1; i <= len; i++) rk[sa[i]] = i; for (i = 0; i < len; height[rk[i++]] = k){ for (k ? k-- : 0, j = sa[rk[i] - 1]; r[i + k] == r[j + k]; k++); } return; } int n; i64 have[maxn]; i64 hs[maxn]; int qsa[20][maxn]; int qh[20][maxn]; int lg2[maxn]; void init_rmq(int st[][maxn],int l,int r){ //从 l 到 r 初始化rmq for (int step = 1; (1 << step) <= r; step++){ for (int i = l; i <= r; i++){ if (i + (1 << (step - 1)) <= r){ st[step][i] = min //最小查询 //max //最大查询 (st[step - 1][i], st[step - 1][i + (1 << (step - 1))]); } else{ st[step][i] = st[step - 1][i]; } } } } int query(int st[][maxn], int l, int r){ //查询 l 到 r 的结果 return min //最小查询 //max //最大查询 (st[lg2[r - l + 1]][l], st[lg2[r - l + 1]][r - (1 << lg2[r - l + 1]) + 1]); } void start(){ da(c, sa, n, 128); get_height(c, sa, n); for (int i = 1; i <= n; i++){ have[i] = n - sa[i] - height[i]; } hs[0] = 0; for (int i = 1; i <= n; i++){ hs[i] = hs[i - 1] + have[i]; } for (int i = 1; i <= n; i++){ qsa[0][i] = sa[i]; qh[0][i] = height[i]; } init_rmq(qsa, 1, n); init_rmq(qh, 2, n); } int find(i64 k,int len){ if (k > hs[len]){ return -1; } else{ int l,r; l = 1; r = len; while (l < r){ int mid = (l + r) / 2; if (hs[mid] >= k){ r = mid; } else{ l = mid + 1; } } return l; } } int findsal(int pos,int hh){ int l = 1; int r = pos; while (l < r){ int mid = (l + r) / 2; int temp = query(qh, mid + 1, pos); if (temp >= hh) { r = mid; } else{ l = mid + 1; } } return l; } int findsar(int pos, int hh){ int l = pos; int r = n; while (l < r){ int mid = (l + r + 1) / 2; int temp = query(qh, pos + 1, mid); if (temp >= hh){ l = mid; } else{ r = mid - 1; } } return r; } int main(){ for (int i = 1; i < 20; i++){ if ((1 << i) < maxn){ lg2[(1 << i)] = i; } } for (int i = 3; i < maxn; i++){ if (lg2[i] == 0){ lg2[i] = lg2[i - 1]; } } while (scanf("%s",c)!=EOF){ n = strlen(c); start(); int Q; cin >> Q; i64 l, r; i64 k, v; l = r = 0; for (int i = 1; i <= Q; i++){ //cin >> v; scanf("%I64d", &v); k = (l ^ r ^ v)+1; int pos = find(k,n); if (pos != -1){ l = sa[pos]; r = n - (hs[pos] - k)-1; int hh = r - l + 1; int ansl = query(qsa, findsal(pos,hh) , findsar(pos, hh)) + 1; int ansr = ansl + hh - 1; l = ansl; r = ansr; printf("%d %d\n", ansl, ansr); } else{ puts("0 0"); l = r = 0; } } } return 0; }
相关文章推荐
- HDU 5008 Boring String Problem 后缀数组 RMQ
- 【后缀数组】 HDOJ 5008 Boring String Problem
- hdu 5008 Boring String Problem(后缀自动机构造后缀树)
- HDU 5008 Boring String Problem
- hdu5008-Boring String Problem(后缀数组专题)
- HDU - 5008 Boring String Problem (后缀数组+二分法+RMQ)
- HDU5008 Boring String Problem(后缀数组 + 二分 + 线段树)
- HDU - 5008 Boring String Problem (后缀数组+二分+RMQ)
- 后缀数组 - hdu5008 Boring String Problem
- HDU 5008 Boring String Problem 后缀数组
- HDU 5008 Boring String Problem(西安网络赛B题)
- hdu 5008 Boring String Problem
- HDU - 5008 Boring String Problem (后缀数组+二分+RMQ)
- HDU 5008 Boring String Problem 后缀数组
- HDU 5008 B - Boring String Problem(非常好的题目)
- hdu 5008 Boring String Problem 后缀数组
- hdu 5008 Boring String Problem 后缀数组
- [后缀数组+二分+rmq] hdu 5008 Boring String Problem
- hdu 5008 Boring String Problem(后缀数组)
- hdu 5008 Boring String Problem