hdu 5008 Boring String Problem(后缀数组)
来源:互联网 发布:红包埋雷软件 编辑:程序博客网 时间:2024/04/25 12:45
每个后缀的所有前缀即为字符串的子串,先处理出每个后缀的所有前缀(与前一个后缀的某前缀相等的前缀除外)的名次区间。
例如aaa这个串。
它有三个后缀
a
aa
aaa
第一个后缀所有的前缀对应的名次区间为[1,1]
第二个后缀对应的区间为[2,2]
第三个后缀对应的区间为[3,3]
如下:
1 a 2 aa 3aaa再比如abcba这个串
1 a 2345abcba67 ba 8910 bcba 111213 cba则每个后缀对应的名次区间分别为 [1,1] [2,5] [6,7] [8,10] [11,13]
求出区间后对于每次询问进行二分查找,找到后再for循环往下找找到l最小的答案。
#include <stdio.h>#include <math.h>#include <stdlib.h>#include <string.h>#include <algorithm>#define ll long longusing namespace std;const int N = 100010;char s[N];int r[N], tx[N], ty[N], rs[N], ranks[N], sa[N], height[N], rmq[N][20]; //rs基数排序bool cmp(int *r, int a, int b, int len){return (r[a] == r[b]) && (r[a + len] == r[b + len]);}void suffix(int n, int m) //n为长度,最大值小于m{int i, j, p, *x = tx, *y = ty, *t;for(i = 0; i < m; ++i) rs[i] = 0;for(i = 0; i < n; ++i) { x[i] = r[i]; ++rs[x[i]];}for(i = 1; i < m; ++i) rs[i] += rs[i - 1];for(i = n - 1; i >= 0; --i) sa[--rs[x[i]]] = i;for(j = p = 1; p < n; j <<= 1, m = p) {for(p = 0, i = n - j; i < n; ++i) y[p++] = i;for(i = 0; i < n; ++i) { if(sa[i] >= j) y[p++] = sa[i] - j; }for(i = 0; i < m; ++i) rs[i] = 0;for(i = 0; i < n; ++i) ++rs[x[y[i]]];for(i = 1; i < m; ++i) rs[i] += rs[i - 1];for(i = n - 1; i >= 0; --i) sa[--rs[x[y[i]]]] = y[i];t = x, x = y, y = t;for(i = 1, p = 1, x[sa[0]] = 0; i < n; ++i) {if(cmp(y, sa[i - 1], sa[i], j)) x[sa[i]] = p - 1;else x[sa[i]] = p++;}}}void calheight(int n){int i, j, k = 0;for(i = 1; i <= n; ++i)ranks[sa[i]] = i;for(i = 0; i < n; ++i) {if(k)--k;j = sa[ranks[i] - 1];while(r[i + k] == r[j + k])++k;height[ranks[i]] = k;}}///////////////////////////////////////////////////////////////////////////////ll a[N],b[N];int n;void check(ll k,ll &l,ll &r){ int left=1,right=n,mid,i; while(left<=right){ mid=(left+right)>>1; if(a[mid]<=k && k<=b[mid]){ l=sa[mid]; r=k-a[mid]+height[mid]+sa[mid]; for(i=mid+1;i<=n;i++){ if(height[i]<r-l+1) break; if(sa[i]<l){ l=sa[i]; r=k-a[mid]+height[mid]+sa[i]; } } l++,r++; return ; } else if(k>b[mid]) left=mid+1; else right=mid-1; } l=r=0; return;}int main(){while(~scanf("%s", s)){int i,q;ll k,left=0,right=0,v;scanf("%d",&q);n = strlen(s);for(i = 0; i < n; ++i)r[i] = s[i];r[n] = 0;suffix(n + 1, 128);calheight(n);a[1]=1,b[1]=n-sa[1]; for(i=2;i<=n;i++){ a[i]=b[i-1]+1; b[i]=n-sa[i]-height[i]+a[i]-1; } for(i=0;i<q;i++){ scanf("%I64d",&v); k=(left^right^v)+1; check(k,left,right); printf("%I64d %I64d\n",left,right); }}return 0;}
0 0
- 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 后缀数组
- HDU 5008 Boring String Problem 后缀数组 RMQ
- [后缀数组+二分+rmq] hdu 5008 Boring String Problem
- HDU - 5008 Boring String Problem (后缀数组+二分+RMQ)
- HDU 5008 Boring String Problem 二分 + 后缀数组
- 【后缀数组】 HDOJ 5008 Boring String Problem
- hdu 5008 Boring String Problem(后缀自动机构造后缀树)
- hdu 5008(2014 ACM/ICPC Asia Regional Xi'an Online ) Boring String Problem(后缀数组&二分)
- hdu5008 Boring String Problem 后缀数组+二分
- hdu5008-Boring String Problem(后缀数组专题)
- hdu5008 Boring String Problem(后缀数组)
- 后缀数组 - hdu5008 Boring String Problem
- hdu 5008 Boring String Problem
- SOJ 1021. Couples
- 网络流之最大流算法(ford-fulkerson)
- UNIX-LINUX平台可执行文件格式分析
- eXeScope之类的程序资源修改器的使用,很牛! 【只是针对VC++和DELPHI写的程序】
- 飘逸的python - 一个简单的AST(抽象语法树)
- hdu 5008 Boring String Problem(后缀数组)
- Linux下的lds链接脚本基础
- java中在方法中定义不定长参数示例
- jkjjkjhjkkkjjkjj
- 写出float x 与“零值”比较的if语句——一道面试题分析
- hdu 3006 枚举集合可以产生的所有并集的集合
- 经济环境监管机构交换机好
- Unity3D -- 图形 -- 视锥体
- 最详细的U-BOOT源码分析及移植