• [USACO2006 DEC] Milk Patterns


    [题目链接]

            https://www.lydsy.com/JudgeOnline/problem.php?id=1717

    [算法]

           首先二分答案 , 然后将后缀分组即可

           详见2009国家集训队论文集之 : 《后缀数组——处理字符串的有利工具》

           时间复杂度 : O(NlogN)

    [代码]

           

    #include <algorithm>
    #include <bitset>
    #include <cctype>
    #include <cerrno>
    #include <clocale>
    #include <cmath>
    #include <complex>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <ctime>
    #include <deque>
    #include <exception>
    #include <fstream>
    #include <functional>
    #include <limits>
    #include <list>
    #include <map>
    #include <iomanip>
    #include <ios>
    #include <iosfwd>
    #include <iostream>
    #include <istream>
    #include <ostream>
    #include <queue>
    #include <set>
    #include <sstream>
    #include <stdexcept>
    #include <streambuf>
    #include <string>
    #include <utility>
    #include <vector>
    #include <cwchar>
    #include <cwctype>
    #include <stack>
    #include <limits.h>
    using namespace std;
    #define MAXN 1500000
     
    int n , k;
    int height[MAXN] , cnt[MAXN] , rk[MAXN] , sa[MAXN] , a[MAXN] , x[MAXN] , y[MAXN];
     
    template <typename T> inline void chkmin(T &x , T y) { x = min(x , y); }
    template <typename T> inline void chkmax(T &x , T y) { x = max(x , y); } 
    template <typename T> inline void read(T &x)
    {
        T f = 1; x = 0;
        char c = getchar();
        for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
        for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
        x *= f; 
    } 
    inline void build_sa()
    {
        memset(cnt , 0 , sizeof(cnt));
        for (int i = 1; i <= n; i++) ++cnt[a[i]];
        for (int i = 1; i <= 1000010; i++) cnt[i] += cnt[i - 1];
        for (int i = 1000010; i >= 1; i--) sa[cnt[a[i]]--] = i;
        rk[sa[1]] = 1;
        for (int i = 2; i <= n; i++) rk[sa[i]] = rk[sa[i - 1]] + (a[sa[i - 1]] != a[sa[i]]);
        for (int k = 1; rk[sa[n]] != n; k <<= 1)
        {
            for (int i = 1; i <= n; i++)
                x[i] = rk[i] , y[i] = (i + k <= n) ? rk[i + k] : 0;
            for (int i = 0; i <= n; i++) cnt[i] = 0;
            for (int i = 1; i <= n; i++) ++cnt[y[i]];
            for (int i = 1; i <= n; i++) cnt[i] += cnt[i - 1];
            for (int i = n; i >= 1; i--) rk[cnt[y[i]]--] = i;
            for (int i = 1; i <= n; i++) cnt[i] = 0;
            for (int i = 1; i <= n; i++) ++cnt[x[i]];
            for (int i = 0; i <= n; i++) cnt[i] += cnt[i - 1];
            for (int i = n; i >= 1; i--) sa[cnt[x[rk[i]]]--] = rk[i];
            rk[sa[1]] = 1;
            for (int i = 2; i <= n; i++) rk[sa[i]] = rk[sa[i - 1]] + (x[sa[i]] != x[sa[i - 1]] || y[sa[i]] != y[sa[i - 1]]);
        }
    }
    inline void get_height()
    {
        int k = 0;
        for (int i = 1; i <= n; i++)
        {
            if (k) --k;
            int j = sa[rk[i] - 1];
            while (a[i + k] == a[j + k]) ++k;
            height[rk[i]] = k;  
        }   
    } 
    inline bool check(int mid)
    {
        int cnt = 1;
        for (int i = 2; i <= n; i++)
        {
            if (height[i] >= mid) 
            {
                ++cnt;
                if (cnt >= k) return true;
            } else cnt = 1;
        }
        return false;
    }
      
    int main()
    {
         
        read(n); read(k);
        for (int i = 1; i <= n; i++) read(a[i]);
        build_sa();
        get_height();
        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;
        }
        for (int i = 1; i <= n; i++)
        {
            ++cnt[a[i]];
            if (cnt[a[i]] >= k) chkmax(ans , 1);
        }
        printf("%d
    " , ans);
         
        return 0;
    }
  • 相关阅读:
    爬虫的基础知识(贰)
    Django内置标签
    WPF ToggleButton Style
    编写一个简单的COM组件
    C# 调用DOS 命令
    【转】 C#中检查网络是否连通的二种方法
    c++中的类型转换
    COM笔记-包容与聚合
    windows笔记-在可执行文件或DLL的多个实例之间共享静态数据
    编程之路
  • 原文地址:https://www.cnblogs.com/evenbao/p/10046814.html
Copyright © 2020-2023  润新知