POJ3693字尾陣列+RMQ
阿新 • • 發佈:2019-01-02
每日,,
只粘程式碼吧,思路一片混亂,等明天想清楚了再說吧,總之就是字尾陣列+RMQ,以及字典序的判斷(=。=| wa到哭
#include<stdio.h> #include<string.h> #define rep(i,n) for(int i = 0;i < n; i++) #include<iostream> #include<math.h> using namespace std; char s[100010]; #define maxn 100000+10 int w[maxn],rk[maxn],sa[maxn],wa[maxn],height[maxn],res[maxn]; void getSa (int len,int up) { int *k = rk,*id = height,*r = res, *cnt = wa; rep(i,up) cnt[i] = 0; rep(i,len) cnt[k[i] = w[i]]++; rep(i,up) cnt[i+1] += cnt[i]; for(int i = len - 1; i >= 0; i--) { sa[--cnt[k[i]]] = i; } //初始化 int d = 1,p = 0; while(p < len){ for(int i = len - d; i < len; i++) id[p++] = i; rep(i,len) if(sa[i] >= d) id[p++] = sa[i] - d;//id儲存了按後h/2排序的的序列,即排第i的後h/2的是原陣列中的哪一個,往前d個找開頭 rep(i,len) r[i] = k[id[i]]; //重新構造串!先對第二關鍵字排序!!!! rep(i,up) cnt[i] = 0; rep(i,len) cnt[r[i]]++; rep(i,up) cnt[i+1] += cnt[i]; for(int i = len - 1; i >= 0; i--) { //在對第一關鍵字排序!!! sa[--cnt[r[i]]] = id[i]; } //同上 swap(k,r); p = 0; k[sa[0]] = p++; //更新字元上限 rep(i,len-1) { if(sa[i]+d < len && sa[i+1]+d <len &&r[sa[i]] == r[sa[i+1]]&& r[sa[i]+d] == r[sa[i+1]+d]) k[sa[i+1]] = p - 1; else k[sa[i+1]] = p++; } //懂了! if(p >= len) return ; //超出len,直接結束 d *= 2,up = p, p = 0; } } void getHeight(int len) { rep(i,len) rk[sa[i]] = i; height[0] = 0; for(int i = 0,p = 0; i < len - 1; i++) { int j = sa[rk[i]-1]; while(i+p < len&& j+p < len&& w[i+p] == w[j+p]) { p++; } height[rk[i]] = p; p = max(0,p - 1); } } int f[maxn][21],ft[maxn]; void rmq(int n){ int i,j; for (i=1;i<=n;i++) f[i][0]=height[i]; for (j=1;j<20;j++) for (i=1;i+(1<<j)-1<=n;i++) f[i][j]=min(f[i][j-1],f[i+(1<<j-1)][j-1]); return ; } int lcp(int a,int b){ int x=rk[a],y=rk[b]; if (x>y) {int t=x; x=y; y=t;} x++; int t=ft[y-x+1]; return min(f[x][t],f[y-(1<<t)+1][t]); } int shu[maxn]; int main() { char xi; int n,up,cas=1,cn; for (int i=0; i<maxn; i++) ft[i]=int(double(log(i))/log(2.00)); while(scanf("%s",s)!=EOF) { if(s[0]=='#') break; xi='z'+1; n=strlen(s); up=0; for(int i=0;i<n;i++) { w[i]=s[i]; up=max(up,w[i]); if(s[i]<xi) xi=s[i]; } w[n]=0; getSa(n+1,200); getHeight(n+1); rmq(n); int tmp,ans=0,rr=0,tt,ll=0,st,sst; for(int l=1; l<n; l++) for(int i=0; i+l<n; i+=l) { st=i; tmp=lcp(i,i+l); rr=tmp/l+1; tt=i-(l-tmp%l); if (tt>=0&&tmp%l!=0) if (lcp(tt,tt+l)>=tmp) { rr=lcp(tt,tt+l)/l+1; st=tt; } // printf("rr==%d\n",i); if(rr>ans) { ans=rr; // printf("i==%d ans==%d tmp==%d\n",i,ans,tmp); cn=0; shu[cn++]=l; } if(rr==ans) { shu[cn++]=l; } } int b=0,c; for(int i=1;i<=n&&!b;i++){ for(int j=0;j<cn;j++){ int tl=shu[j]; if(lcp(sa[i],sa[i]+tl)>=(ans-1)*tl){ st=sa[i]; ll=tl*ans; b=1; break; } } } printf("Case %d: ",cas++); if(ans>1){ for(int i=st;i<st+ll;i++) printf("%c",s[i]); printf("\n"); } else printf("%c\n",xi); } return 0; }