• P3426 [POI2005]SZA-Template


    P3426 [POI2005]SZA-Template

    链接

    分析:

      首先T一定是S的一个前缀,也是一个后缀。

      判断一个前缀s[1...i]是不是满足条件,那么求出s[1...i]在s中出现的所有位置,如果相邻的两个位置之间的距离的最大值小于等于i,那么就是满足的。

      于是可以建出fail树,每次从根到n走,那么出现的位置的个数是递减的,于是链表维护即可。

    代码:

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    #include<cctype>
    #include<set>
    #include<queue>
    #include<vector>
    #include<map>
    #include<bitset>
    using namespace std;
    typedef long long LL;
    
    inline int read() {
        int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
        for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
    }
    
    const int N = 1000005;
    int p[N], L[N], R[N], to[N], mx;
    vector<int> T[N];
    char s[N];
    
    void del(int x) {
        if (x) {
            int a = L[x], b = R[x];
            mx = max(mx, b - a);
            L[b] = a, R[a] = b;
        }
        for (auto v : T[x]) if (v != to[x]) del(v);
    }
    int main() {
        scanf("%s", s + 1);
        int n = strlen(s + 1);
        p[1] = 0;
        for (int j = 0, i = 2; i <= n; ++i) {
            while (j && s[j + 1] != s[i]) j = p[j];
            if (s[j + 1] == s[i]) j ++;
            p[i] = j;
        }
        for (int i = 1; i <= n; ++i) T[p[i]].push_back(i);
        for (int i = n; i; i = p[i]) to[p[i]] = i;
        for (int i = 1; i <= n; ++i) L[i] = i - 1, R[i] = i + 1;
        int now = 1;
        del(0);
        while (now < mx) { del(now), now = to[now]; }
        cout << now;
        return 0;
    }

  • 相关阅读:
    Java代码是怎么运行的
    Java单例模式
    redis分布式锁实现
    zuul2.0
    配置ssh免密钥登陆多台从机
    Nifi-install-config
    Configure Access to Multiple Clusters
    kubernetes集群搭建(kubeadm,kubelet)
    shell 编程
    系统管理
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10595246.html
Copyright © 2020-2023  润新知