初见SA
用了一个常见的按$height$分组的操作:二分答案,然后按$height$分组,遇到一个$height$小于$mid$的就丢进下一组并更新答案,如果最多的那组不少于$k$个说明可行
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N=20005; 6 int uni[N],num[N],sec[N],bkt[N]; 7 int SA[N],rnk[N],hgt[N]; 8 int n,k,l,r,ans,siz; 9 void Basenum_Sort() 10 { 11 register int i; 12 for(i=1;i<=siz;i++) bkt[i]=0; 13 for(i=1;i<=n;i++) bkt[rnk[i]]++; 14 for(i=1;i<=siz;i++) bkt[i]+=bkt[i-1]; 15 for(i=n;i;i--) SA[bkt[rnk[sec[i]]]--]=sec[i]; 16 } 17 void Suffix_Sort() 18 { 19 register int i; 20 int pw=1,cnt=0; 21 Basenum_Sort(); 22 while(cnt<n) 23 { 24 cnt=0; 25 for(i=1;i<=pw;i++) sec[++cnt]=n-pw+i; 26 for(i=1;i<=n;i++) if(SA[i]>pw) sec[++cnt]=SA[i]-pw; 27 Basenum_Sort(); swap(rnk,sec); rnk[SA[1]]=cnt=1; 28 for(i=2;i<=n;i++) cnt+=(sec[SA[i-1]]!=sec[SA[i]]||sec[SA[i-1]+pw]!=sec[SA[i]+pw]),rnk[SA[i]]=cnt; 29 pw<<=1,siz=cnt; 30 } 31 } 32 void Getting_Height() 33 { 34 int p=0; 35 for(int i=1;i<=n;i++) 36 if(rnk[i]!=1) 37 { 38 int r=SA[rnk[i]-1]; 39 while(num[r+p]==num[i+p]) p++; 40 hgt[rnk[i]]=p; if(p>0) p--; 41 } 42 hgt[1]=0; 43 } 44 bool check(int x) 45 { 46 register int i; 47 int len=0,lst=1; 48 for(i=1;i<=n;i++) 49 if(hgt[i]<x) 50 len=max(i-lst,len),lst=i; 51 len=max(n-lst+1,len); 52 return len>=k; 53 } 54 int main() 55 { 56 register int i; 57 scanf("%d%d",&n,&k); 58 for(i=1;i<=n;i++) 59 scanf("%d",&num[i]),uni[i]=num[i]; 60 sort(uni+1,uni+1+n),siz=unique(uni+1,uni+1+n)-uni-1; 61 for(i=1;i<=n;i++) 62 rnk[i]=lower_bound(uni+1,uni+1+siz,num[i])-uni,sec[i]=i; 63 Suffix_Sort(); Getting_Height(); l=0,r=n; 64 while(l<=r) 65 { 66 int mid=(l+r)/2; 67 if(check(mid)) ans=mid,l=mid+1; 68 else r=mid-1; 69 } 70 printf("%d",ans); 71 return 0; 72 }
Upd:SAM对SA的全面替换已完成
这题丢给SAM就没啥可说的了,直接按定义来就行
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<unordered_map> 5 #define umap unordered_map 6 using namespace std; 7 const int N=40005; 8 umap<int,int> trs[N]; 9 int p[N],noww[N],goal[N]; 10 int fth[N],len[N],siz[N]; 11 int rd,lth,kth,cnt,tot,lst,ans; 12 void Link(int f,int t) 13 { 14 noww[++cnt]=p[f]; 15 goal[cnt]=t,p[f]=cnt; 16 } 17 void Insert(int ch) 18 { 19 int nde=lst,newn=++tot; lst=newn; 20 siz[newn]=1,len[newn]=len[nde]+1; 21 while(nde&&!trs[nde].count(ch)) 22 trs[nde][ch]=newn,nde=fth[nde]; 23 if(!nde) fth[newn]=1; 24 else 25 { 26 int tran=trs[nde][ch]; 27 if(len[tran]==len[nde]+1) 28 fth[newn]=tran; 29 else 30 { 31 int rnde=++tot; 32 len[rnde]=len[nde]+1,trs[rnde]=trs[tran]; 33 fth[rnde]=fth[tran],fth[tran]=fth[newn]=rnde; 34 while(nde&&trs[nde][ch]==tran) 35 trs[nde][ch]=rnde,nde=fth[nde]; 36 } 37 } 38 } 39 void DFS(int nde) 40 { 41 for(int i=p[nde];i;i=noww[i]) 42 DFS(goal[i]),siz[nde]+=siz[goal[i]]; 43 } 44 int main() 45 { 46 register int i; 47 scanf("%d%d",<h,&kth),lst=tot=1; 48 for(i=1;i<=lth;i++) scanf("%d",&rd),Insert(rd); 49 for(i=1;i<=tot;i++) Link(fth[i],i); DFS(1); 50 for(i=1;i<=tot;i++) 51 if(siz[i]>=kth) ans=max(ans,len[i]); 52 printf("%d",ans); 53 return 0; 54 }