zoukankan      html  css  js  c++  java
  • SPOJ 687:REPEATS——后缀数组+RMQ

    题面

      洛谷

    解析

      先奉上YYR的PPT

       

       基本思路这张PPT已经讲清楚了,但还有一些其他的细节

      我们确定了$L*t$与$L*(t+1)$后,显然不能暴力向后跳或向前跳。考虑向后跳最多跳$LCP(L*t, L*(t+1))$个点,因此这个可以用后缀数组+RMQ预处理出来,快速查询。再考虑向前跳,向前跳最多产生1个循环节,因为如果有多个循环节的话,必定存在一个更小的t使得向前跳跳到相同起点,并且最多产生一个循环节,那么什么时候会产生一个循环节呢?

      令$len = LCP(L*t, L*(t+1))$, 此时循环节个数为$res = len / L + 1$, 超出循环节的部分为$k' = len % L$,显然如果能向前跳至少$k = L - k'$个点,就可以产生1个循环节,即满足$LCP(L*t-k, L*t-k+L) geqslant L$时,$ res++$

     代码:

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int maxn = 50004;
    
    int T, n, ans;
    int sa[maxn], rk[maxn], fir[maxn], sec[maxn], c[maxn], hei[maxn];
    char s[maxn];
    
    void Build_SA()
    {
        int m = 26;
        for(int i = 1; i <= n; ++i)
            fir[i] = s[i] - 'a' + 1;
        for(int i = 0; i <= m; ++i)
            c[i] = 0;
        for(int i = 1; i <= n; ++i)
            c[fir[i]] ++;
        for(int i = 1; i <= m; ++i)
            c[i] += c[i-1];
        for(int i = n; i; --i)
            sa[c[fir[i]]--] = i;
        for(int k = 1; k <= n; k <<= 1)
        {
            int t = 0;
            for(int i = n - k + 1; i <= n; ++i)
                sec[++t] = i;
            for(int i = 1; i <= n; ++i)
                if(sa[i] > k)
                    sec[++t] = sa[i] - k;
            for(int i = 0; i <= m; ++i)
                c[i] = 0;
            for(int i = 1; i <= n; ++i)
                c[fir[sec[i]]] ++;
            for(int i = 1; i <= m; ++i)
                c[i] += c[i-1];
            for(int i = n; i; --i)
                sa[c[fir[sec[i]]]--] = sec[i], sec[i] = 0;
            for(int i = 1; i <= n; ++i)
                swap(fir[i], sec[i]);
            t = 0;
            fir[sa[1]] = ++t;
            for(int i = 2; i <= n; ++i)
                if(sec[sa[i]] != sec[sa[i-1]] || sec[sa[i]+k] != sec[sa[i-1]+k])
                    fir[sa[i]] = ++t;
                else
                    fir[sa[i]] = t;
            if(t >= n)
                break;
            m = t;
        }
        for(int i = 1; i <= n; ++i)
            fir[i] = sec[i] = 0;
    }
    
    void Get_hei()
    {
        int h = 0;
        for(int i = 1; i <= n; ++i)
            rk[sa[i]] = i;
        for(int i = 1; i <= n; ++i)
        {
            int t = sa[rk[i]-1];
            while(s[t+h] == s[i+h])     h++;
            hei[rk[i]] = h;
            h = max(0, h - 1);
        }
    }
    
    int lg[maxn], mn[20][maxn];
    
    void RMQ()
    {
        for(int i = 1; i <= n; ++i)
            mn[0][i] = hei[i];
        for(int j = 1; j <= lg[n]; ++j)
            for(int i = 1; i + (1<<j) - 1 <= n; ++i)
                mn[j][i] = min(mn[j-1][i], mn[j-1][i+(1<<(j-1))]);
    }
    
    int query(int x, int y)
    {
        if(x > y)    swap(x, y);
        return min(mn[lg[y-x]][x+1], mn[lg[y-x]][y-(1<<lg[y-x])+1]);
    }
    
    int main()
    {
        lg[0] = -1;
        for(int i = 1; i <= 50000; ++i)
            lg[i] = lg[i>>1] + 1;
        scanf("%d", &T);
        while(T--)
        {
            scanf("%d", &n);
            char c[5];
            for(int i = 1; i <= n; ++i)
            {
                scanf("%s", c);
                s[i] = c[0];
            }
            s[n+1] = 0;
            Build_SA();
            Get_hei();
            RMQ();
            ans = 1;
            for(int i = 1; i <= n; ++i)
                for(int j = 1; j + i <= n; j += i)
                {
                    int l = query(rk[j], rk[j+i]);
                    int res = l / i + 1, k = i - l % i;
                    if(j - k && query(rk[j-k], rk[j-k+i]) >= i)
                        res++;
                    ans = max(ans, res);
                    j += l / i * i;
                }
            printf("%d
    ", ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    双剑合璧Nacos结合Sentinel实现流量安全控制(一):Sentinel是什么?Sentinel核心库和控制台
    微服务架构系列之Nacos集群环境搭建
    微服务架构系列之Nacos 配置核心概念
    微服务架构之Nacos配置中心之配置MySQL数据库
    微服务系列之Nacos配置中心之一:Nacos介绍与安装
    一文带您读懂什么是Spring Cloud与Spring Cloud Alibaba
    idea搭建springboot项目(一)
    mysql不常用命令
    mysql安装
    idea快捷键
  • 原文地址:https://www.cnblogs.com/Joker-Yza/p/11348702.html
Copyright © 2011-2022 走看看