poj 3261 Milk Patterns
http://poj.org/problem?id=3261
题意:
求可重复的最长出现k次子串
后缀数组求出height后分组
从大到小每句长度,并查集合并
#include<cstdio> #include<vector> #include<iostream> #include<algorithm> #define N 20001 using namespace std; int n,m,tot; int a[N],has[N]; int v[N]; int p=0,q=1; int sa[2][N],rk[2][N],height[N]; int fa[N],siz[N]; vector<int>V[N]; void read(int &x) { x=0; char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); } } void mul(int k,int *sa,int *rk,int *SA,int *RK) { for(int i=1;i<=n;++i) v[rk[sa[i]]]=i; for(int i=n;i;--i) if(sa[i]>k) SA[v[rk[sa[i]-k]]--]=sa[i]-k; for(int i=n-k+1;i<=n;++i) SA[v[rk[i]]--]=i; for(int i=1;i<=n;++i) RK[SA[i]]=RK[SA[i-1]]+(rk[SA[i]]!=rk[SA[i-1]]||rk[SA[i]+k]!=rk[SA[i-1]+k]); } void presa() { for(int i=1;i<=n;++i) v[a[i]]++; for(int i=1;i<=tot;++i) v[i]+=v[i-1]; for(int i=1;i<=n;++i) sa[p][v[a[i]]--]=i; for(int i=1;i<=n;++i) rk[p][sa[p][i]]=rk[p][sa[p][i-1]]+(a[sa[p][i]]!=a[sa[p][i-1]]); for(int k=1;k<n;k<<=1,swap(p,q)) mul(k,sa[p],rk[p],sa[q],rk[q]); } void get_height() { int j; for(int i=1,k=0;i<=n;++i) { j=sa[p][rk[p][i]-1]; while(a[i+k]==a[j+k]) k++; height[rk[p][i]]=k; if(k) k--; } } int find(int i) { return fa[i]==i ? i : fa[i]=find(fa[i]); } void unionn(int u,int v) { u=find(u); v=find(v); siz[v]+=siz[u]; fa[u]=v; } void solve() { for(int i=1;i<=n;++i) fa[i]=i,siz[i]=1; for(int i=2;i<=n;++i) V[height[i]].push_back(i); int w,s; for(int i=n;i;--i) { s=V[i].size(); if(!s) continue; for(int j=0;j<s;++j) { w=V[i][j]; if(find(sa[p][w-1])!=find(sa[p][w])) unionn(sa[p][w-1],sa[p][w]); if(w<n && height[w+1]>=i && find(sa[p][w+1])!=find(sa[p][w])) unionn(sa[p][w+1],sa[p][w]); if(siz[find(sa[p][w])]>=m) { printf("%d",i); return; } } } } int main() { read(n); read(m); for(int i=1;i<=n;++i) read(a[i]),has[i]=a[i]; sort(has+1,has+n+1); tot=unique(has+1,has+n+1)-has-1; for(int i=1;i<=n;++i) a[i]=lower_bound(has+1,has+tot+1,a[i])-has; presa(); get_height(); solve(); return 0; }