HDU 5008 Boring String Problem 后缀数组
来源:互联网 发布:mysql update join on 编辑:程序博客网 时间:2024/03/28 19:41
【题目大意】
有一个字符串,将它的所有非空子串去重后排序,求排序第k大的字串位置,如果有多个,输出最前面的位置。
【思路】
按后缀排序后,所有子串就是这些后缀的前缀。排名为i的后缀,会有n - sa[i]个前缀,并且,他们的字典大小是按长度排序的。对于后缀i-1和后缀i,后缀会出现heigt[i]个重复串,哪些不重复的串,任意一个都比以前出现的串,字典序更大。那么,使用二分,就可以找到第k的串的一个位置。
剩下的问题,就是怎么去找到位置最前面的串。因为后缀数组的固有性质(相似度越高的,就越在一起),我们可以利用二分,找到一个连续区间,这个区间的每个后缀和找到的那个解的公共前缀包括原来的那个解。之后,就是找这个区间,哪个串是最先出现的(这可以用rmq搞定)。
//#pragma comment(linker, "/STACK:102400000,102400000")#include<cstdio>#include<cstring>#include<vector>#include<queue>#include<cmath>#include<cctype>#include<string>#include<algorithm>#include<iostream>#include<ctime>#include<map>#include<set>using namespace std;#define MP(x,y) make_pair((x),(y))#define PB(x) push_back(x)typedef __int64 LL;//typedef unsigned __int64 ULL;/* ****************** */const int INF = 1000111222;const double INFF = 1e100;const double eps = 1e-8;const int mod = 1000000007;const int NN = 100009;const int MM = 400010;/* ****************** */int a[NN];char ss[NN];int wa[NN],wb[NN],wv[NN],wss[NN],sa[NN];int rank[NN],height[NN];int rmq[NN][20],long2[NN];int rmq1[NN][20];LL sum[NN];int cmp(int *r,int a,int b,int l){return r[a]==r[b]&&r[a+l]==r[b+l];}void da(int *r,int n,int m){ int i,j,p,*x=wa,*y=wb,*t; for(i=0;i<m;i++)wss[i]=0; for(i=0;i<n;i++)wss[x[i]=r[i]]++; for(i=1;i<m;i++)wss[i]+=wss[i-1]; for(i=n-1;i>=0;i--)sa[--wss[x[i]]]=i; for(j=1,p=1;p<n;j*=2,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<n;i++)wv[i]=x[y[i]]; for(i=0;i<m;i++)wss[i]=0; for(i=0;i<n;i++)wss[wv[i]]++; for(i=1;i<m;i++)wss[i]+=wss[i-1]; for(i=n-1;i>=0;i--)sa[--wss[wv[i]]]=y[i]; for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; } return;}void calheight(int *r,int n){ int i,j,k=0; for(i=1;i<=n;i++)rank[sa[i]]=i; for(i=0;i<n;height[rank[i++]]=k) for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++); return;}void initRMQ(int n){ int i,j,en; long2[1]=0; for(i=2;i<=n;i++) { long2[i]=long2[i-1]+(i==(i&(-i))); } for(i=1;i<=n;i++)rmq[i][0]=height[i]; for(j=1;j<=long2[n];j++) { en=n+1-(1<<j); for(i=1;i<=en;i++) rmq[i][j]=min(rmq[i][j-1],rmq[ i+(1<<(j-1)) ][j-1]); }}int lcp(int i,int j,int n){ // i=rank[i],j=rank[j]; if(i==j)return n - sa[i]; if(i>j)swap(i,j); i++; int k=long2[j-i+1]; int ans=min(rmq[i][k],rmq[ j+1-(1<<k) ][k]); return ans;}void init(int n){ int i, j, en; for (i = 1; i <= n; i ++) rmq1[i][0] = sa[i]; for (j = 1; j <= long2[n]; j ++) { en = n + 1 - (1<<j); for (i = 1; i <= en; i ++) rmq1[i][j] = min(rmq1[i][j-1], rmq1[i+(1<<(j-1))][j-1]); }}int GET_MIN(int st,int en){ int k = long2[en-st+1]; return min(rmq1[st][k], rmq1[ en+1-(1<<k) ][k]);}void goo(LL &st,LL &en,int n){ LL l, r, mid, len = en - st + 1; int k = rank[st]; // printf("k==%d\n",k); l = 1; r = k; while (l < r) { mid = (l + r) >> 1; if(lcp(mid, k, n) >= len) r = mid; else l = mid + 1; } st = l; // cout<<"st=="<<st<<endl; l = k; r = n; while (l < r) { mid = (l + r + 1) >> 1; if (lcp(mid, k, n) >= len) l = mid; else r = mid - 1; } en = l; // cout<<"en=="<<en<<endl; st = GET_MIN(st, en); en = st + len; st ++; printf("%I64d %I64d\n",st,en);}void fun(LL &st,LL &en,LL k,int n){ if(k > sum[n]) { st = en = 0; puts("0 0"); return; } int l; l = lower_bound(sum+1, sum+1+n, k) - sum; k -= sum[l-1]; st = sa[l]; en = sa[l] + height[l] + k - 1; // printf("[] == %I64d %I64d\n",st+1,en+1); goo(st, en, n);}void solve(int n,int m){ LL l, r, t, k; l = r = 0; while (m--) { scanf("%I64d", &t); k = (l^r^t) + 1; fun(l, r, k, n); }}int main(){ int i, n, m; while (scanf("%s", ss) != EOF) { n = strlen(ss); for (i = 0; i < n; i ++) { a[i] = ss[i] - 'a' + 1; } a[n] = 0; da(a, n+1, 30); calheight(a, n); initRMQ(n); init(n); sum[0] = 0; for (i = 1; i <= n; i ++) { sum[i] = n - sa[i] - height[i]; sum[i] += sum[i-1]; } scanf("%d", &m); solve(n, m); } 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
- Linux内核 RPS/RFS功能详细测试分析
- Android Fragments详解六:处理fragmenst的生命周期
- Python 类继承,__bases__, __mro__, super
- oracle主机ip修改无法正常启动,报错:ORA-00600:internal error code
- java设计模式之中介者模式
- HDU 5008 Boring String Problem 后缀数组
- 虚方法【只有虚方法或者抽象方法才能被子类方法重写】
- 常用代码段Android Shortcut操作(快捷方式)
- 【北京站】IT运维免费培训火爆进行时,还有惊喜礼品哦~
- poj 2082——Terrible Sets
- 创建指定时间段内的日历信息
- 恢复出厂设置壁纸偏移patch
- 储存器-大端模式与小端模式
- IOS判断是否有效银行卡号