PAT T1005 Programming Pattern
建立后缀数组,遍历height数组找到连续大于len的最长子序列~
#include<bits/stdc++.h> using namespace std; const int maxn=1e7+14; char s[maxn]; int n; int rk[maxn]; int sa[maxn]; int height[maxn]; int tmp[maxn]; int c[maxn]; int t1[maxn]; int t2[maxn]; void build_sa (char s[],int n,int m) { int i,j,p; int *x=t1; int *y=t2; for (i=0;i<m;i++) c[i]=0; for (i=0;i<n;i++) c[x[i]=s[i]]++; for (i=1;i<m;i++) c[i]+=c[i-1]; for (i=n-1;i>=0;i--) sa[--c[x[i]]]=i; for (j=1;j<=n;j<<=1) { p=0; for (i=n-j;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<m;i++) c[i]=0; for (i=0;i<n;i++) c[x[y[i]]]++; for (i=1;i<m;i++) c[i]+=c[i-1]; for (i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i]; swap(x,y); p=1; x[sa[0]]=0; for (i=1;i<n;i++) x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+j]==y[sa[i]+j]?p-1:p++; if (p>=n) break; m=p; } } void getHeight (char s[],int n) { int i,j,k=0; for (i=0;i<=n;i++) rk[sa[i]]=i; for (i=0;i<n;i++) { if (k) k--; j=sa[rk[i]-1]; while (s[i+k]==s[j+k]) k++; height[rk[i]]=k; } } int main () { int len; scanf ("%d",&len); getchar (); cin.getline (s,maxn); n=strlen(s); build_sa (s,n+1,128); getHeight (s,n); int cnt=0; int res=0; int ans=1; for (int i=0;i<=n;i++) { if (height[i]>=len) ans++; else ans=1; if (sa[i]+len<=n&&cnt<ans) { cnt=ans; res=sa[i]; } } for (int i=0;i<len;i++) printf ("%c",s[res+i]); printf (" %d",cnt); return 0; }