hdu 5853 Jong Hyok and String (二分+后缀数组+RMQ)
来源:互联网 发布:风险矩阵分析法 编辑:程序博客网 时间:2024/04/27 17:51
Jong Hyok and String
Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 301 Accepted Submission(s): 66
Total Submission(s): 301 Accepted Submission(s): 66
Problem Description
Jong Hyok loves strings. One day he gives a problem to his friend you. He writes down n strings Pi in front of you, and asks m questions. For i-th question, there is a string Qi. We called strange set(s) = {(i, j) | s occurs in Pi and j is the position of its last character in the current occurence}. And for ith question, you must answer the number of different strings t which satisfies strange set(Qi) = strange set(t) and t is a substring of at least one of the given n strings.
Input
First line contains T, a number of test cases.
For each test cases, there two numbers n, m and then there are n strings Pi and m strings Qj.(i = 1…n, j = 1…m)
1 <= T <= 10
1 <= n <= 100000
1 <= m<= 500000
1 <=|Pi|<=100000
1 <=|Qi|<=100000
∑ni=1|Pi|≤100000
File size is less than 3.5 megabytes.
For each test cases, there two numbers n, m and then there are n strings Pi and m strings Qj.(i = 1…n, j = 1…m)
1 <= T <= 10
1 <= n <= 100000
1 <= m<= 500000
1 <=|Pi|<=100000
1 <=|Qi|<=100000
File size is less than 3.5 megabytes.
Output
For each test case, first line contains a line “Case #x:”, x is the number of the case.
For each question, you should print one integer in one line.
For each question, you should print one integer in one line.
Sample Input
12 2abaabaab
Sample Output
Case #1:12Hintstrange set(“a”) ={(1, 1), (1, 3), (2, 1)}.strange set(“ab”) ={(1, 2), (2, 2)}.strange set(“b”) ={(1, 2), (2, 2)}.分析:考虑到P串长度总和为10w,我们把每个P串倒着连成一串,中间用特殊符隔开,由于特殊符号需要10w个,所以我们要把字符换成int,然后跑后缀数组,就可以得到每个后缀的排名,查询时也把Q串倒序,并换成int,然后去每个后缀里面找哪些可以和这个倒序的Q串匹配,由于每个后缀已经排好序,所以我们用二分查找得到下界lower和上界upper,如果找不到,那么答案就是0。先定义一个maxlen,如果lower==upper,那么maxlen为排名为lower的这个后缀的不包含特殊符的最大前缀,如果lower<upper,那么maxlen=min(height[lower+1]...height[upper]),这里取最小值可以用RMQ处理height值得到,然后最后的答案ans=maxlen-max(height[lower],height[upper+1])#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<vector>#include<algorithm>using namespace std;const int N=200010;const int maxn=100010;int cmp(int *r,int a,int b,int l){ return (r[a]==r[b])&&(r[a+l]==r[b+l]);}int wa[N],wb[N],ws[N],wv[N];int Rank[N],height[N];void DA(int *r,int *sa,int n,int m){ int i,j,p,*x=wa,*y=wb,*t; for(i=0;i<m;i++) ws[i]=0; for(i=0;i<n;i++) ws[x[i]=r[i]]++; for(i=1;i<m;i++) ws[i]+=ws[i-1]; for(i=n-1;i>=0;i--) sa[--ws[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++) ws[i]=0; for(i=0;i<n;i++) ws[wv[i]]++; for(i=1;i<m;i++) ws[i]+=ws[i-1]; for(i=n-1;i>=0;i--) sa[--ws[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++; } int k=0; for(i=1;i<n;i++) Rank[sa[i]]=i; for(i=0;i<n-1; height[Rank[i++]] = k ) for(k?k--:0,j=sa[Rank[i]-1]; r[i+k]==r[j+k]; k++);}char s[maxn];int a[maxn];int r[N],sa[N],C[N][20];int pos[N];void rmq(int nn){ for(int i=1;i<nn;i++) C[i][0]=height[i]; for(int j=1;(1<<j)<nn;j++) for(int i=1;i+(1<<j)-1<nn;i++) C[i][j]=min(C[i][j-1],C[i+(1<<(j-1))][j-1]);}int getmin(int l,int r){ int k=0; while((1<<(k+1))<=r-l+1) k++; return min(C[l][k],C[r-(1<<k)+1][k]);}int cmp(int pos,int len,int num){ for(int i=0;i<len;i++) { if(r[i+pos]>a[i]) return 1; else if(r[i+pos]<a[i]) return -1; } return 0;}int main(){ int T; scanf("%d",&T); for(int ca=1;ca<=T;ca++) { int n,m; scanf("%d%d",&n,&m); int num=0; for(int i=1;i<=n;i++) { scanf("%s",s); int len=strlen(s); reverse(s,s+len); int mm=num+len-1; for(int j=0;j<len;j++) { pos[num]=mm; r[num++]=s[j]-'a'+1; } r[num++]=26+i; } r[num++]=0; DA(r,sa,num,n+27); height[num]=0; rmq(num); printf("Case #%d:\n",ca); while(m--) { scanf("%s",s); int len=strlen(s); reverse(s,s+len); for(int i=0;i<len;i++) a[i]=s[i]-'a'+1; int lower=-1,upper=-1; int L,R; L=1,R=num-1; while(L<=R) { int mid=(L+R)>>1; int k=cmp(sa[mid],len,num); if(k==0) { lower=mid; R=mid-1; } else if(k==1) R=mid-1; else L=mid+1; } L=1,R=num-1; while(L<=R) { int mid=(L+R)>>1; int k=cmp(sa[mid],len,num); if(k==0) { upper=mid; L=mid+1; } else if(k==1) R=mid-1; else L=mid+1; } if(lower==-1) { puts("0"); continue; } if(lower==upper) { printf("%d\n",(pos[sa[lower]]-sa[lower]+1)-max(height[lower],height[lower+1])); continue; } int ans=getmin(lower+1,upper)-max(height[lower],height[upper+1]); printf("%d\n",ans); } } return 0;}
0 0
- hdu 5853 Jong Hyok and String (二分+后缀数组+RMQ)
- hdoj5853Jong Hyok and String【后缀数组+二分+rmq】
- hdu 5853 Jong Hyok and String
- HDU 5853 Jong Hyok and String
- Hdu 5853 Jong Hyok and String
- 2016MUTC9-1010 Jong Hyok and String
- hdu 5008 (后缀数组 + rmq +二分)
- [后缀数组+二分+rmq] hdu 5008 Boring String Problem
- HDU - 5008 Boring String Problem (后缀数组+二分+RMQ)
- HDU 5558 (后缀数组 二分 RMQ)
- HDU 6194 string string string 后缀数组+rmq
- hdu 6194 string string string 后缀数组+rmq+容斥
- hdu5008 Boring String Problem 后缀数组+二分+RMQ
- HDU 6194 string string string 后缀数组 + RMQ(线段树)
- HDU 5008 Boring String Problem 后缀数组 RMQ
- hdu6194 string string string 后缀数组 + RMQ
- HDU 4622 后缀数组+RMQ
- hdu 6194 后缀数组+RMQ
- 【TBB】缺少MSVCR80问题
- 机器学习-贝叶斯分类
- 遇见C++ Lambda
- Trying to open unclosed connection
- 透明度与十六进制代码转换
- hdu 5853 Jong Hyok and String (二分+后缀数组+RMQ)
- 装饰(Decorator)——对象结构型模式
- 一致性哈希
- 【JZOJ4709】【NOIP2016提高A组模拟8.17】Matrix
- 增强图像细节(附C++代码)
- OpenSceneGraph实现的NeHe OpenGL教程 - 第四十二课
- jQuery选择器详解
- PHPExcel中文开发手册翻译版(2-1)
- 手机验证码DEMO