zoukankan      html  css  js  c++  java
  • 【洛谷 P5341】 [TJOI2019]甲苯先生和大中锋的字符串(后缀自动机)

    题目链接
    建出(sam),求出parent tree上每个点的(endpos)集合大小。
    如果等于(k),说明到达这个点的都可以。给((len[fa(i)],len[i]])(cnt)都加(1),差分即可。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int MAXN = 100010;
    struct SAM{
        int ch[26];
        int len, fa;
    }sam[MAXN << 1];
    int las = 1, cnt = 1, f[MAXN << 1];
    struct Edge{
        int next, to;
    }e[MAXN << 1];
    int head[MAXN << 1], num;
    inline void Add(int from, int to){
        e[++num].to = to; e[num].next = head[from]; head[from] = num;
    }
    inline void add(int c){
        int p = las; int np = las = ++cnt;
        sam[np].len = sam[p].len + 1; f[cnt] = 1;
        for(; p && !sam[p].ch[c]; p = sam[p].fa) sam[p].ch[c] = np;
        if(!p) sam[np].fa = 1;
        else{
            int q = sam[p].ch[c];
            if(sam[q].len == sam[p].len + 1) sam[np].fa = q;
            else{
                int nq = ++cnt; sam[nq] = sam[q];
                sam[nq].len = sam[p].len + 1;
                sam[q].fa = sam[np].fa = nq;
                for(; p && sam[p].ch[c] == q; p = sam[p].fa) sam[p].ch[c] = nq;
            }
        }
    }
    char a[MAXN];
    int k, T, v[MAXN];
    void dfs(int u){
        for(int i = head[u]; i; i = e[i].next){
            dfs(e[i].to);
            f[u] += f[e[i].to];
        }
    }
    int main(){
        scanf("%d", &T);
        while(T--){
            scanf("%s%d", a + 1, &k);
            int len = strlen(a + 1);
            for(int i = 1; i <= len; ++i)
                add(a[i] - 'a');
            for(int i = 2; i <= cnt; ++i)
                Add(sam[i].fa, i);
            dfs(1);
            int ans = -1, Max = -1;
            for(int i = 2; i <= cnt; ++i)
                if(f[i] == k)
                    --v[sam[sam[i].fa].len], ++v[sam[i].len];
            for(int i = len - 1; i >= 1; --i)
                v[i] += v[i + 1];
            for(int i = 1; i <= len; ++i)
                if(v[i] && v[i] >= Max){
                    Max = v[i];
                    ans = i;
                }
            printf("%d
    ", ans);
            for(int i = 1; i <= cnt; ++i)
                memset(sam[i].ch, 0, sizeof sam[i].ch), sam[i].len = sam[i].fa = f[i] = head[i] = 0;
            cnt = 1; num = 0; memset(v, 0, sizeof v); las = 1;
        }
        return 0;
    }
    
    
  • 相关阅读:
    构建之法阅读笔记04
    团队项目
    构建之法阅读笔记03
    第6周学习进度
    求最大子数组03
    四则运算4(完结)
    第5周学习进度
    敏捷开发概述
    第4周学习进度
    构建之法阅读笔记01
  • 原文地址:https://www.cnblogs.com/Qihoo360/p/11031094.html
Copyright © 2011-2022 走看看