[后缀数组+枚举] hdu 2459 && poj 3693 Maximum repetition substring
来源:互联网 发布:java aes 编辑:程序博客网 时间:2024/04/30 19:43
题意:求重复次数最多的连续子串,要求输出字典序最小的连续子串。
思路:这做这题之前可以先做做 spoj 687 ,是不需要输出子串的,只求次数。
那么求法就是枚举每一个长度,看看这个长度的子串能连续出现几次。
那么能出现几次怎么求呢。我们假设长度为i,那么如果从fuck[j]开始 长度为i的子串连续出现了。
那么必然 fuck[j]==fuck[j+i],那么出现次数便是 lcp(fuck[j],fuck[j+i)/i+1 因为要加上本身的。
但是会出现一个问题,比如这样一个串 aababababab
实际上最长的长度是2 连续次数是5 串是 ababababab 但是我们枚举的时候并没有枚举到这种情况
我们枚举的答案是7/2+1=4
事实上就是 lcp(fuck[2],fuck[4])=k=7 这样其实多出来了1个长度,那么我们要往左边移动这样一个剩余的长度(i-k%i)
也就是再比较一下 lcp(fuck[2-1],fuck[2-1+2])=8>=k 那么就多出来了一个 就把此时的次数加1!
这样问题就解决了。
然后这道题要求出字典序最小的,那么我们就在过程中记录最多次数的ans所对应的长度i有多少个
然后通过sa数组进行枚举,一旦符合就跳出,便是字典序最小的了!
还有一个很神奇的事情,这题居然poj的数据比hdu的水
我一定不是在黑hdu~~
代码:
#include"cstdlib"#include"cstdio"#include"cstring"#include"cmath"#include"queue"#include"algorithm"#include"iostream"#include"map"using namespace std;#define N 100020int wa[N],wb[N],wv[N],wws[N];int sa[N],ra[N],height[N];int v[N],dp[N][30],Log[N],a[N];char fuck[N];int cmp(int *r,int a,int b,int l){ return r[a]==r[b]&&r[a+l]==r[b+l];}void da(int n,int m){ int i,j,p,*x=wa,*y=wb; for(i=0; i<m; i++) wws[i]=0; for(i=0; i<n; i++) wws[x[i]=v[i]]++; for(i=1; i<m; i++) wws[i]+=wws[i-1]; for(i=n-1; i>=0; i--) sa[--wws[x[i]]]=i; for(j=1,p=1; p<n; j*=2,m=p) { for(i=n-j,p=0; 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++) wws[i]=0; for(i=0; i<n; i++) wws[wv[i]]++; for(i=1; i<m; i++) wws[i]+=wws[i-1]; for(i=n-1; i>=0; i--) sa[--wws[wv[i]]]=y[i]; for(swap(x,y),p=1,i=1,x[sa[0]]=0; i<n; i++) x[sa[i]]=cmp(y,sa[i],sa[i-1],j)?p-1:p++; } return ;}void gethei(int n){ int i,j,k=0; for(i=1; i<=n; i++) ra[sa[i]]=i; for(i=0; i<n; i++) { if(k) k--; j=sa[ra[i]-1]; while(v[i+k]==v[j+k]) k++; height[ra[i]]=k; } return ;}void rmqinit(int n){ int m=Log[N]; //log2(N) int i,j; for(i=1;i<=n;i++) dp[i][0]=height[i]; for(i=1;i<=m;i++) //dp的方法构造rmq { for(j=1;j+(1<<i)-1<=n;j++) dp[j][i]=min(dp[j][i-1],dp[j+(1<<i>>1)][i-1]); } return ;}int lcp(int a,int b) //查找rmq求lcp{ a=ra[a]; b=ra[b]; if(a>b) swap(a,b); a++; //这个一定要记得 int m=Log[b-a+1]; return min(dp[a][m],dp[b-(1<<m)+1][m]);}int main(){ int cas=1; Log[0]=-1; for(int i=1;i<=N;i++) Log[i]=(i&(i-1))?Log[i-1]:Log[i-1]+1; while(scanf("%s",fuck),strcmp(fuck,"#")!=0) { int i,j; int ans=0,cnt=0; int len=strlen(fuck); for(i=0;i<len;i++) v[i]=fuck[i]-'a'+2; v[len]=0; da(len+1,50); gethei(len); rmqinit(len); for(i=1;i<=len;i++) //枚举长度i { for(j=0;j<len;j+=i) //j+=i 大大缩小了复杂度! { int k=lcp(j,j+i); int tep=j-(i-k%i); //往左偏移 int sum=k/i+1; if(tep>=0&&k%i!=0&&lcp(tep,tep+i)>=k) sum++; if(sum>ans) //a数组存的是能够达成最大连续次数的字符串的长度 改变则cnt赋为0 { ans=sum; cnt=0; a[cnt++]=i; } else if(sum==ans) a[cnt++]=i; //相等则添加 } } for(i=1;i<=len;i++) //sa数组 保证字典序神器 从前往后遍历sa通过a数组枚举长度 符合条件就停止 就是字典序最小 { for(j=0;j<cnt;j++) { int tep=a[j]; if(lcp(sa[i],sa[i]+tep)>=(ans-1)*tep) break; } if(j!=cnt) break; } printf("Case %d: ",cas++); for(int k=0;k<ans*a[j];k++) printf("%c",fuck[sa[i]+k]); puts(""); } return 0;}
0 0
- [后缀数组+枚举] hdu 2459 && poj 3693 Maximum repetition substring
- 后缀数组 POJ 3693 && hdu 2459 Maximum repetition substring
- poj 3693 Maximum repetition substring //后缀数组
- poj 3693 Maximum repetition substring (后缀数组)
- poj 3693 Maximum repetition substring(后缀数组)
- poj 3693 Maximum repetition substring(后缀数组)
- 【后缀数组】【poj 3693】Maximum repetition substring
- POJ 3693 Maximum Repetition Substring 后缀数组
- 【后缀数组】 HDOJ 2459 && POJ 3693 Maximum repetition substring
- HDU 2459 PKU 3693 Maximum repetition substring 后缀数组 RMQ
- poj 3693 Maximum repetition substring(后缀数组好题)
- POJ 3693 Maximum repetition substring(RMQ+后缀数组)
- POJ 3693 Maximum repetition substring (后缀数组)
- poj 3693 Maximum repetition substring(有点麻烦的后缀数组)
- POJ 3693 Maximum repetition substring(后缀数组神题)
- poj 3693 Maximum repetition substring 后缀数组+RMQ
- POJ 3693 - Maximum repetition substring (后缀数组)
- POJ 3693 Maximum repetition substring 后缀数组 暴力 rmq
- 8月份的工作记录
- HDU 3468 Treasure Hunting
- Magento左边导航菜单调出方法
- 本次小孙女违法色粉吗不和你过分
- 一个支持函数,浮点数表达式求值算法
- [后缀数组+枚举] hdu 2459 && poj 3693 Maximum repetition substring
- 黑马程序员--static 关键字
- 吃嫩草但是农村的建设发挥女接待方面是否 扩大覆盖的
- ,跪拜雷锋劳动法避免的事方式等方面的客流高峰的某个地方客流高峰但是
- 产品详情页单栏显示
- 陈年旧事快点发货上岛咖啡vjksdfbdfb
- 真是郁闷
- [leetcode]Binary Tree Maximum Path Sum
- 黑马程序员--单例设计模式