zoukankan      html  css  js  c++  java
  • BZOJ 4516. [Sdoi2016]生成魔咒【SAM 动态维护不同子串数量】

    [Sdoi2016]生成魔咒

    动态维护不同子串的数量
    想想如果只要查询一次要怎么做,那就是计算各个点的(len[u]-len[link[u]])然后求和即可,现在要求动态更新,我们可以保存一个答案,然后每次更新后缀链接的时候,如果是连接的话就要加上(len[u]-len[link[u]]),断开的话就要减去(len[u]-len[link[u]]),每次输出答案即可

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<cmath>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    #include<string>
    #include<algorithm>
    #include<stack>
    using namespace std;
    void ____(){ ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0); }
    const int MAXN = 2e5+7;
    using LL = int_fast64_t;
    
    struct SAM{
        int len[MAXN],link[MAXN],tot,last;
        LL ret = 0;
        map<int,int> ch[MAXN];
        SAM(){ link[0] = -1; }
        void extend(int x){
            int np = ++tot, p = last;
            len[np] = len[p] + 1;
            while(p!=-1 and !ch[p].count(x)){
                ch[p].insert(make_pair(x,np));
                p = link[p];
            }
            if(p==-1) link[np] = 0;
            else{
                int q = ch[p][x];
                if(len[p]+1==len[q]) link[np] = q;
                else{
                    int clone = ++tot;
                    len[clone] = len[p] + 1;
                    link[clone] = link[q];
                    ret += len[clone] - len[link[clone]];
                    ch[clone] = ch[q];
                    ret -= len[q] - len[link[q]];
                    link[q] = link[np] = clone;
                    ret += len[q] - len[clone];
                    while(p!=-1 and ch[p].count(x) and ch[p].at(x)==q){
                        ch[p].at(x) = clone;
                        p = link[p];
                    }
                }
            }   
            last = np;
            ret += len[np] - len[link[np]];
        }
    }sam;
    int n;
    int main(){
        scanf("%d",&n);
        for(int i = 1; i <= n; i++){
            int x; scanf("%d",&x);
            sam.extend(x);
            printf("%lld
    ",sam.ret);
        }
        return 0;
    }
    
  • 相关阅读:
    10.cocos2dx C++为Sprite添加触摸事件监听器
    9.多彩的幕布layer
    8.ZOrder
    7.cocos精灵创建和绘制
    6.cocos2d设置定时器
    5.cocos2d锚点
    4.cocos场景和层的调用
    文件导入导出
    两个整数相乘是否超限
    倒置字符串函数reverse
  • 原文地址:https://www.cnblogs.com/kikokiko/p/12706116.html
Copyright © 2011-2022 走看看