您的位置:首页 > 其它

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: