【后缀数组】 HDOJ 5008 Boring String Problem
来源:互联网 发布:pwd linux 编辑:程序博客网 时间:2024/04/25 20:31
通过后缀数组可以找到第K的串,然后用二分找到最左边的编号。。。
#include <iostream> #include <queue> #include <stack> #include <map> #include <set> #include <bitset> #include <cstdio> #include <algorithm> #include <cstring> #include <climits> #include <cstdlib>#include <cmath>#include <time.h>#define maxn 100005#define maxm 40005#define eps 1e-10#define mod 1000000007#define INF 999999999#define lowbit(x) (x&(-x))#define mp mark_pair#define ls o<<1#define rs o<<1 | 1#define lson o<<1, L, mid #define rson o<<1 | 1, mid+1, R typedef long long LL;//typedef int LL;using namespace std;LL qpow(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base;base=base*base;b/=2;}return res;}LL powmod(LL a, LL b){LL res=1,base=a;while(b){if(b%2)res=res*base%mod;base=base*base%mod;b/=2;}return res;}void scanf(int &__x){__x=0;char __ch=getchar();while(__ch==' '||__ch=='\n')__ch=getchar();while(__ch>='0'&&__ch<='9')__x=__x*10+__ch-'0',__ch = getchar();}LL gcd(LL _a, LL _b){if(!_b) return _a;else return gcd(_b, _a%_b);}// headchar s[maxn];int sa[maxn], c[maxn], t1[maxn], t2[maxn];int rank[maxn], height[maxn];void build(int n, int m){ int *x = t1, *y = t2, p; for(int i = 0; i < m; i++) c[i] = 0; for(int i = 0; i < n; i++) c[x[i] = s[i]]++; for(int i = 1; i < m; i++) c[i] += c[i-1]; for(int i = n-1; i >= 0; i--) sa[--c[x[i]]] = i; for(int k = 1; k <= n; k <<= 1) { p = 0; for(int i = n-k; i < n; i++) y[p++] = i; for(int i = 0; i < n; i++) if(sa[i] >= k) y[p++] = sa[i] - k; for(int i = 0; i < m; i++) c[i] = 0; for(int i = 0; i < n; i++) c[x[y[i]]]++; for(int i = 1; i < m; i++) c[i] += c[i-1]; for(int i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i]; p = 1, swap(x, y), x[sa[0]] = 0; for(int 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; }}void getheight(int n){ int k = 0; for(int i = 0; i <= n; i++) rank[sa[i]] = i; for(int i = 0; i < n; i++) { if(k) k--; int j = sa[rank[i] - 1]; while(s[i + k] == s[j + k]) k++; height[rank[i]] = k; }}int p[maxn];LL st1[maxn][20], st2[maxn][20];LL sum[maxn];void init(int n, int *a, LL (*t)[20]){ p[0] = -1; for(int i = 1; i <= n; i++) p[i] = i & (i-1) ? p[i-1] : p[i-1] + 1; for(int i = 1; i <= n; i++) t[i][0] = a[i]; for(int j = 1; j <= p[n]; j++) for(int i = 1; i + (1 << j) - 1 <= n; i++) t[i][j] = min(t[i][j-1], t[i + (1 << (j-1))][j-1]);}LL query(int l, int r, LL (*t)[20]){ LL k = p[r - l + 1]; return min(t[l][k], t[r - (1 << k) + 1][k]);}LL lcp(int a, int b){ if(a > b) swap(a, b); return query(a+1, b, st1);}int find(int n, LL x){ LL bot = 0, top = n, mid, res; while(top >= bot) { mid = (top + bot) >> 1; if(sum[mid] >= x) top = mid - 1, res = mid; else bot = mid + 1; } return res;}int search(int pos, int n, LL k){ int bot = pos + 1, top = n, mid, res = -1; while(top >= bot) { mid = (top + bot) >> 1; if(lcp(pos, mid) < k) top = mid - 1; else bot = mid + 1, res = mid; } if(res != -1) return query(pos, res, st2) + 1; return sa[pos] + 1;}void work(void){ int n = strlen(s), l, r, kk, now, tmp;LL k, v; build(n+1, 128); getheight(n); init(n, height, st1); init(n, sa, st2); sum[0] = l = r = 0; for(int i = 1; i <= n; i++) sum[i] = n - sa[i] - height[i]; for(int i = 1; i <= n; i++) sum[i] += sum[i-1]; scanf("%d", &kk); while(kk--) { scanf("%I64d", &v); k = (l ^ r ^ v) + 1; if(k > sum[n]) printf("0 0\n"), l = r = 0; else { now = find(n, k); tmp = k - sum[now-1] + height[now]; l = min(sa[now] + 1, search(now, n, tmp)); r = l + tmp - 1; printf("%d %d\n", l, r); } }}int main(void){ while(scanf("%s", s)!=EOF) work(); return 0;}
0 0
- 【后缀数组】 HDOJ 5008 Boring String Problem
- hdu 5008 Boring String Problem(后缀数组)
- HDU 5008 Boring String Problem 后缀数组
- hdu 5008 Boring String Problem(后缀数组)
- hdu 5008 Boring String Problem 【后缀数组】
- hdu 5008 Boring String Problem 后缀数组
- HDU 5008 Boring String Problem 后缀数组
- HDOJ 5008 Boring String Problem
- HDU 5008 Boring String Problem 后缀数组 RMQ
- [后缀数组+二分+rmq] hdu 5008 Boring String Problem
- HDU - 5008 Boring String Problem (后缀数组+二分+RMQ)
- HDU 5008 Boring String Problem 二分 + 后缀数组
- hdu5008 Boring String Problem 后缀数组+二分
- hdu5008-Boring String Problem(后缀数组专题)
- hdu5008 Boring String Problem(后缀数组)
- 后缀数组 - hdu5008 Boring String Problem
- hdu5008 Boring String Problem 后缀数组+二分+RMQ
- hdu 5008 Boring String Problem(后缀自动机构造后缀树)
- Java transient关键字
- [iOS] 初探 iOS8 中的 Size Class
- python 排序
- Android不常见系统控件一览
- java.math.BigInteger使用心得总结
- 【后缀数组】 HDOJ 5008 Boring String Problem
- <meta> 标签 --文件更新
- HDU4998Rotate(矩阵变换)
- 深入理解Java序列化中的SerialVersionUid
- diff和patch
- android按键连续按下事件处理
- android 左右滑动事件
- UnsatisfiedLinkError errordlopen failed: cannot locate symbol "rand"
- sqlserver内存释放