zoukankan      html  css  js  c++  java
  • [bzoj1717][Milk Patterns 产奶的模式]

    题目链接

    思路

    先求出后缀数组,并且求出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;
    }
    

    一言

    就算你诚实,可生活一样在欺骗你。

  • 相关阅读:
    20145207《信息安全系统设计基础》第十周学习总结
    《信息安全系统设计基础》第九周学习总结
    《信息安全系统设计基础》第九周学习总结
    20145207《信息安全系统设计基础》第一次实验实验报告
    qrcode插件生成二维码
    条形码生成工具
    客户端实现分页
    泛型+反射+三层实现工厂
    调用百度地图
    MVC爬取网页指定内容到数据库
  • 原文地址:https://www.cnblogs.com/wxyww/p/10146562.html
Copyright © 2011-2022 走看看