HDU 5558 后缀数组
思路:
这是一个错误的思路, 因为数据水才过= =
首先求出来后缀数组
把rank插到set里
每回差i两边离i近的rank值,更新
如果LCP相同,暴力左(右)继续更新sa的最小值
//By SiriusRen #include <bits/stdc++.h> using namespace std; const int N=100050; char s[N]; int n,T,base[N],f[N][20],I=1; int cntA[N],cntB[N],A[N],B[N],sa[N],tsa[N],rk[N],ht[N]; void SA(){ for(int i=1;i<=256;i++)cntA[i]=0; for(int i=1;i<=n;i++)cntA[s[i]]++; for(int i=1;i<=256;i++)cntA[i]+=cntA[i-1]; for(int i=n;i;i--)sa[cntA[s[i]]--]=i; rk[sa[1]]=1; for(int i=2;i<=n;i++)rk[sa[i]]=rk[sa[i-1]]+(s[sa[i]]!=s[sa[i-1]]); for(int l=1;rk[sa[n]]<n;l<<=1){ memset(cntA,0,sizeof(cntA)); memset(cntB,0,sizeof(cntB)); for(int i=1;i<=n;i++)cntA[A[i]=rk[i]]++,cntB[B[i]=(i+l<=n?rk[i+l]:0)]++; for(int i=1;i<=n;i++)cntA[i]+=cntA[i-1],cntB[i]+=cntB[i-1]; for(int i=n;i;i--)tsa[cntB[B[i]]--]=i; for(int i=n;i;i--)sa[cntA[A[tsa[i]]]--]=tsa[i]; rk[sa[1]]=1; for(int i=2;i<=n;i++)rk[sa[i]]=rk[sa[i-1]]+(A[sa[i]]!=A[sa[i-1]]||B[sa[i]]!=B[sa[i-1]]); } for(int i=1,j=0;i<=n;i++){ j=j?j-1:0; while(s[i+j]==s[sa[rk[i]-1]+j])j++; ht[rk[i]]=j; }base[0]=-1; for(int i=1;i<=n;i++)f[i][0]=ht[i],base[i]=base[i>>1]+1; for(int j=1;j<=18;j++) for(int i=1;i+(1<<(j-1))<=n;i++) f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]); } set<int>S;set<int>::iterator it; int LCP(int x,int y){ x++;int t=base[y-x+1]; return min(f[x][t],f[y-(1<<t)+1][t]); } int main(){ for(scanf("%d",&T);I<=T;I++){ printf("Case #%d:\n",I); scanf("%s",s+1),n=strlen(s+1);SA(); S.clear();int t=1; while(1){ it=S.upper_bound(rk[t]);int tmp=0,rec=N; while(it!=S.end()){ if(LCP(rk[t],*it)>=tmp)tmp=LCP(rk[t],*it),rec=min(sa[*it],rec); else break; it++; }it=S.upper_bound(rk[t]); while(it!=S.begin()){ it--;int tt=LCP(*it,rk[t]); if(tt>tmp)tmp=tt,rec=sa[*it]; else if(tt==tmp)rec=min(sa[*it],rec); else break; } if(!tmp){printf("-1 %d\n",s[t]);tmp=1;} else printf("%d %d\n",tmp,rec-1); for(int i=1;i<=tmp;i++)S.insert(rk[t]),t++; if(t>n)break; } } }