[bzoj1717][Milk Patterns 產奶的模式]
阿新 • • 發佈:2018-12-19
題目連結
思路
先求出字尾陣列,並且求出LCP。二分一下長度len。check的時候就是看有沒有連續的k個字尾的LCP大於len。也就是判斷是不是有連續的k-1個height大於len。
程式碼
#include<cstdio> #include<iostream> using namespace std; typedef long long ll; const int N = 20000+10; ll read() { ll x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1;c = getchar(); } while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); } return x * f; } int s[N],sa[N],height[N],rk[N],c[N * 100],x[N],y[N]; int n,m,K,h[N]; void get_sa() { for(int i = 1;i <= n;++i) ++c[x[i] = s[i]]; for(int i = 2;i <= m;++i) c[i] += c[i - 1]; for(int i = n;i >= 1;--i) sa[c[x[i]]--] = i; for(int k = 1;k <= n;k <<= 1) { int num = 0; for(int i = n - k + 1;i <= n;++i) y[++num] = i; for(int i = 1;i <= n;++i) if(sa[i] > k) y[++num] = sa[i] - k; for(int i = 1;i <= m;++i) c[i] = 0; for(int i = 1;i <= n;++i) ++c[x[i]]; for(int i = 2;i <= m;++i) c[i] += c[i - 1]; for(int i = n;i >= 1;--i) { sa[c[x[y[i]]]--] = y[i]; y[i] = 0; } swap(x,y); num = 1; x[sa[1]] = 1; for(int i = 2;i <= n;++i) { x[sa[i]] = (y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k]) ? num : ++num; } if(num >= n) break; m = num; } } void get_height() { for(int i = 1;i <= n;++i) rk[sa[i]] = i; int k = 0; for(int i = 1;i <= n;++i) { if(rk[i] == 1) continue; if(k) --k; int j = sa[rk[i] - 1]; while(s[i + k] == s[j + k] && j + k <= n && i + k <= n) ++k; height[rk[i]] = h[i] = k; } } int check(int x) { int now = 0; for(int i = 1;i <= n;++i) { if(height[i] >= x) { now ++; if(now >= K - 1) return 1; } else now = 0; } return 0; } void erfen() { int l = 1,r = n,ans = 0; while(l <= r) { int mid = (l + r) >> 1; if(check(mid)) ans = mid,l = mid + 1; else r = mid - 1; } cout<<ans; } int main() { n = read();K = read(); for(int i = 1;i <= n;++i) s[i] = read(),m = max(m,s[i]); get_sa(); get_height(); erfen(); return 0; }