HDU 5558 后缀数组
来源:互联网 发布: 阿里云oss设置http头 编辑:程序博客网 时间:2024/06/21 02:53
点击打开链接
题意:从第一个字符开始,找到一个从0到当前位置i之前的与i开始的字符串的最长匹配长度及位置,长度相同时,要位置小的,若存在,位置+最长长度,否则+1
思路:15年合肥的现场题目,据说牌子发不完了,这道题的题目数据变弱后才可以将牌子发光,HDU的应该也是弱数据的版本,但是也不太好处理,看了大牛的思路才自己照着样子写了写,大牛的做法,其实我就是完全的按照神犇的做法写的,大家可以去看他的博客,思路就是对于当前的位置i,它的排名找出来,然后它的前边和后边是可能有与其有匹配情况的,也只有这个情况才能匹配,然后找这两部分就行,如果已经找到的长度是K,那么当下一个长度不够K时,跳出即可,这样看i与i+1的匹配长度为L,i+1与i+2的匹配长度为L1,那么i与i+2的匹配长度一定是两者取小的那个,所以再找到一个比K小的,后面都是比K小的,这样就降低了复杂度,但是还是不知道能不能过了现场的题目,然后先是预处理一下左右可到的区间,这都是在高度数组上进行的,然后跑一遍找就可以了,写到这发现其实不予处理也可以,因为那个小于K那个已经很优化了,刚刚测试一下,也过了,慢了一点而已
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;typedef long long ll;const int inf=0x3f3f3f3f;const int MAXN=1000010;int wa[MAXN],wb[MAXN],wv[MAXN],ww[MAXN];int sa[MAXN],lcp[MAXN],Rank[MAXN],rank1[MAXN],vis[MAXN];char str[MAXN];inline bool cmp(int *r,int a,int b,int len){ return r[a]==r[b]&&r[a+len]==r[b+len];} void construct_sa(int n,int m){ int i,j,p,*x=wa,*y=wb,*t;n++; for(i=0;i<m;i++) ww[i]=0; for(i=0;i<n;i++) ww[x[i]=str[i]]++; for(i=1;i<m;i++) ww[i]+=ww[i-1]; for(i=n-1;i>=0;i--) sa[--ww[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++) ww[i]=0; for(i=0;i<n;i++) ww[wv[i]=x[y[i]]]++; for(i=1;i<m;i++) ww[i]+=ww[i-1]; for(i=n-1;i>=0;i--) sa[--ww[wv[i]]]=y[i]; for(t=x,x=y,y=t,x[sa[0]]=0,p=i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; }}void construct_lcp(int n){ for(int i=0;i<=n;i++) rank1[sa[i]]=i; int h=0; lcp[0]=0; for(int i=0;i<n;i++){ int j=sa[rank1[i]-1]; if(h>0) h--; for(;j+h<n&&i+h<n;h++) if(str[i+h]!=str[j+h]) break; lcp[rank1[i]-1]=h; }}int fa[MAXN],son[MAXN];int main(){ int T,cas=1; scanf("%d",&T); while(T--){ scanf("%s",str); int len=strlen(str); memset(fa,0,sizeof(fa)); memset(son,0,sizeof(son)); construct_sa(len,300);sa[len+1]=inf; construct_lcp(len); for(int i=1;i<=len;i++){ if(lcp[i-1]==0) fa[i]=i; else fa[i]=fa[i-1]; } for(int i=len;i>0;i--){ if(lcp[i]==0||i==len) son[i]=i; else son[i]=son[i+1]; } printf("Case #%d:\n",cas++); for(int i=0;i<len;){ if(i==0){ printf("-1 %d\n",(int)str[i]); i++;continue; } int min1=0,pos=inf,fen=rank1[i]; int max1; max1=lcp[fen]; for(int j=fen;j<=son[fen];j++){ max1=min(max1,lcp[j]); if(max1<min1) break; if(sa[j+1]>=i) continue; if(max1>min1){ min1=max1;pos=sa[j+1]; }else if(max1==min1&&pos>sa[j+1]) pos=sa[j+1]; } if(fen-1>=fa[fen]) max1=lcp[fen-1]; for(int j=fen-1;j>=fa[fen];j--){ max1=min(max1,lcp[j]); if(max1<min1) break; if(sa[j]>=i) continue; if(max1>min1){ min1=max1;pos=sa[j]; }else if(max1==min1&&pos>sa[j]) pos=sa[j]; } if(min1==0){ printf("-1 %d\n",(int)str[i]); i++; }else{ printf("%d %d\n",min1,pos); i+=min1; } } } return 0;}
- HDU 5558 后缀数组
- HDU 5558 (后缀数组 二分 RMQ)
- hdu 4416 后缀数组
- hdu 4436 后缀数组
- hdu 3518后缀数组
- 后缀数组 HDU 4436
- hdu 3518 后缀数组
- HDU 3518 后缀数组
- hdu 4436 后缀数组
- HDU 4416 后缀数组
- hdu 2492后缀数组
- hdu 4029 后缀数组
- hdu 4416 后缀数组
- hdu 4691 后缀数组
- hdu 3518 后缀数组
- hdu 4622 后缀数组
- hdu 5442 (后缀数组)
- HDU 3518 后缀数组
- Hibernate:No row with the given identifier exists
- 22.使用MAT对Dump文件进行分析实战
- ZooKeeper 基本API使用
- 毛玻璃效果就是这么唯美
- oracle表分区详解
- HDU 5558 后缀数组
- Beta 版软件如何成功发布App
- 安卓获取电池信息
- mysql处理海量数据时的一些优化查询速度方法
- NYOJ 1057 寻找最大数(三)
- 【马仔创业记】一只猴子的创业独白(5)心理咨询行业痛点分析
- SpringMVC-处理请求参数
- JDK各个版本的新特性jdk1.5-jdk8
- 正则表达式 判断手机号码是否合法