poj 1743Maximum repetition substring(后缀数组+RMQ+重复次数最多的连续重复子串))
2015-09-15 19:22
435 查看
题意:重复次数最多的连续重复子串,只能说是一个神题目啊,论文上点了些思路。
就这样吧。。。。
就这样吧。。。。
#include<cstdio> #include<iostream> #include<algorithm> #include<string> #include<cstring> using namespace std; #define LL long long #define cl(a,b) memset(a,b,size(a)) const int maxn=100010; /* 我的后缀数组和论文的后缀数组, 计算出来的lcp高度数组有一个下标的偏移。 我的是从0开始的,论文的是从1开始的 */ int n,k; int rank[maxn],tmp[maxn],sa[maxn],lcp[maxn]; char s[maxn]; int cmp(int i,int j){ if(rank[i]!=rank[j])return rank[i]<rank[j]; int ri=i+k<=n?rank[i+k]:-1; int rj=j+k<=n?rank[j+k]:-1; return ri<rj; } void getSa(){ n=strlen(s); for(int i=0;i<=n;i++){ sa[i]=i; rank[i]=i<n?s[i]:-1; } for(k=1;k<=n;k<<=1){ sort(sa,sa+n+1,cmp); tmp[sa[0]]=0; for(int i=1;i<=n;i++){ tmp[sa[i]]=tmp[sa[i-1]]+cmp(sa[i-1],sa[i]); } for(int i=0;i<=n;i++)rank[i]=tmp[i]; } } void getLcp(){ // n=strlen(s); for(int i=0;i<=n;i++)rank[sa[i]]=i; int h=0; lcp[0]=0; for(int i=0;i<n;i++){ int j=sa[rank[i]-1]; if(h>0)h--; while(i+h<n&&j+h<n&&s[i+h]==s[j+h])h++; lcp[rank[i]-1]=h; } } int mm[maxn]; int dp[maxn][20]; void initRMQ(int n){ mm[0]=-1; dp[0][0]=0; for(int i=1;i<=n;i++){ mm[i]=(i&(i-1))==0?mm[i-1]+1:mm[i-1]; dp[i][0]=i; } for(int j=1;j<=mm ;j++){ for(int i=1;i+(1<<j)-1<n;i++){ int a=lcp[dp[i][j-1]]; int b=lcp[dp[i+(1<<(j-1))][j-1]]; if(a<b)dp[i][j]=dp[i][j-1]; else dp[i][j]=dp[i+(1<<(j-1))][j-1]; } } } int askRMQ(int i,int j){ int t=mm[j-i+1]; j-=(1<<t)-1; int a=dp[i][t]; int b=dp[j][t]; return lcp[a]<lcp[b]?a:b; } int askLCP(int a,int b){ a=rank[a]; b=rank[b]; if(a>b)swap(a,b); return lcp[askRMQ(a,b-1)];//b-1,后缀的实现不同,lcp的有效范围也是不同的 } int ans[maxn]; int main(){ int cas=1; while(~scanf("%s",s)&&s[0]!='#'){ getSa();getLcp();initRMQ(n); // printf("lcp = "); // for(int i=0;i<n;i++){ // printf(" %d,",lcp[i]); // } // printf("\n"); // while(true){ // int a,b; // cin>>a>>b; // printf("==%d\n",lcp[askRMQ(a,b)]); // } int cnt=0,mx=0; for(int l=1;l<n;l++){ for(int i=0;i+l<n;i+=l){ int t1=askLCP(i,i+l); int step=t1/l+1; int kk=i-(l-t1%l); if(kk>=0&&t1%l){ if(askLCP(kk,kk+l)>=t1)step++; } if(step>mx){ mx=step; cnt=0; ans[cnt++]=l; } else if(mx==step){ ans[cnt++]=l; } } } int len=-1,st; for(int i=1;i<=n&&len==-1;i++){ for(int j=0;j<cnt;j++){ int l=ans[j]; if(askLCP(sa[i],sa[i]+l)>=(mx-1)*l){ len=l; st=sa[i]; break; } } } s[st+len*mx]='\0'; // printf("len = %d,st = %d,mx = %d\n",len,st,mx); printf("Case %d: %s\n",cas++,s+st); } return 0; }
相关文章推荐
- 使用GCD
- linux下C/C++,多线程pthread
- CVE-2014-4113:飓风熊猫(HURRICANE PANDA)Win64bit提起权0day破绽
- 保持各工程师的单线性
- 我的团队管理经验
- halcon函数笔记
- 诡异事件之电脑连wifi时狂跑流量
- Android常用控件之SoundPool
- ios 数据持久化初级
- 杰出人士的七种共性之2-独善其身
- halcon资料
- 三目运算符 注意事项
- CSS单行、多行文本溢出显示省略号
- AtionErrors和ActionMessages的区别
- UIImageView
- Fundation构架
- iOS 手机短信验证码等待时间
- Linux磁盘和文件系统管理(6)_链接文件 ln
- Linux磁盘和文件系统管理(5)_创建交换分区
- 9.18工作日誌,系統定位,自定義viewgroup,放射獲取注入的類