zoukankan      html  css  js  c++  java
  • 【bzoj2555】SubString


    *题目描述:
    懒得写背景了,给你一个字符串init,要求你支持两个操作

    (1):在当前字符串的后面插入一个字符串
    
    (2):询问字符串s在当前字符串中出现了几次?(作为连续子串)
    
    你必须在线支持这些操作。
    

    *输入:
    第一行一个数Q表示操作个数
    第二行一个字符串表示初始字符串init
    接下来Q行,每行2个字符串Type,Str
    Type是ADD的话表示在后面插入字符串。
    Type是QUERY的话表示询问某字符串在当前字符串中出现了几次。
    为了体现在线操作,你需要维护一个变量mask,初始值为0
    2555
    读入串Str之后,使用这个过程将之解码成真正询问的串TrueStr。
    询问的时候,对TrueStr询问后输出一行答案Result
    然后mask = mask xor Result
    插入的时候,将TrueStr插到当前字符串后面即可。
    HINT:ADD和QUERY操作的字符串都需要解压


    *输出:


    *样例输入:
    2
    A
    QUERY B
    ADD BBABBBBAAB


    *样例输出:
    0


    *提示:
    40 % 的数据字符串最终长度 <= 20000,询问次数<= 1000,询问总长度<= 10000
    100 % 的数据字符串最终长度 <= 600000,询问次数<= 10000,询问总长度<= 3000000
    新加数据一组–2015.05.20


    *来源:
    Ctsc模拟赛By 洁妹


    *题解:
    用link-cut tree维护SAM。lct维护的是fail树的子树大小,因为是动态插入字符串,有可能一些节点需要换父亲,所以需要lct。


    *代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    
    #ifdef WIN32
        #define LL "%I64d"
    #else
        #define LL "%lld"
    #endif
    
    #ifdef CT
        #define debug(...) printf(__VA_ARGS__)
        #define setfile() 
    #else
        #define debug(...)
        #define filename ""
        #define setfile() freopen(filename".in", "r", stdin); freopen(filename".out", "w", stdout);
    #endif
    
    #define R register
    #define getc() (S == T && (T = (S = B) + fread(B, 1, 1 << 15, stdin), S == T) ? EOF : *S++)
    #define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b))
    #define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b))
    #define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0)
    #define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0)
    char B[1 << 15], *S = B, *T = B;
    inline int FastIn()
    {
        R char ch; R int cnt = 0; R bool minus = 0;
        while (ch = getc(), (ch < '0' || ch > '9') && ch != '-') ;
        ch == '-' ? minus = 1 : cnt = ch - '0';
        while (ch = getc(), ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0';
        return minus ? -cnt : cnt;
    }
    #define maxn 6000010
    char str[maxn];
    struct lct *null;
    struct lct
    {
        lct *fa, *ch[2];
        int sum, val;
        inline bool type()
        {
            return fa -> ch[1] == this;
        }
        inline bool check()
        {
            return fa -> ch[type()] == this;
        }
        inline void update()
        {
            sum = val + ch[0] -> sum + ch[1] -> sum;
        }
        inline void modify(R int x)
        {
            val += x; sum += x;
        }
        inline void rotate()
        {
            R lct *f = fa;
            R bool d = type();
            (fa = f -> fa), f -> check() ? fa -> ch[f -> type()] = this : 0;
            (f -> ch[d] = ch[!d]) != null ? ch[!d] -> fa = f : 0;
            f -> fa = this;
            ch[!d] = f;
            f -> update();
        }
        inline void splay()
        {
            for ( ; check(); rotate())
                if (fa -> check())
                    (type() != fa -> type() ? this : fa) -> rotate();
            update();
        }
        inline lct *access()
        {
            R lct *i = this, *j = null;
            for ( ; i != null; i = (j = i) -> fa)
            {
                i -> splay();
                i -> modify(i -> ch[1] -> sum - j -> sum);
                i -> ch[1] = j;
                i -> update();
            }
        }
        inline void link(R lct *f)
        {
            splay();
            (fa = f) -> access();
            f -> splay();
            f -> modify(sum);
        }
        inline void cut()
        {
            access();
            splay();
            ch[0] = ch[0] -> fa = null;
            update();
        }
    } mem[maxn];
    struct sam *head;
    struct sam
    {
        sam *fa, *next[2];
        int max;
        inline void modify(R sam *f)
        {
            if (fa) (mem + (this - head) + 1) -> cut();
            (mem + (this - head) + 1) -> link(mem + ((fa = f) - head) + 1);
        }
        inline int query()
        {
            R lct *p = mem + (this - head + 1);
            p -> access();
            p -> splay();
            return p -> val;
        }
    } sam_mem[maxn << 1], *tot = sam_mem, *cur = sam_mem;
    inline sam *newnode(R int v)
    {
        mem[++tot - sam_mem + 1] = (lct) {null, null, null, v, v};
        return tot;
    }
    inline void extend(R int w)
    {
        R sam *p = cur, *np = newnode(1);
        (cur = np) -> max = p -> max + 1;
        for( ; p && !p -> next[w]; p = p -> fa)
            p -> next[w] = np;
        if(!p) np -> modify(sam_mem);
        else
        {
            R sam *q = p -> next[w];
            if(q -> max == p -> max + 1)
                np -> modify(q);
            else
            {
                R sam *nq = newnode(0);
                memcpy(nq -> next, q -> next, sizeof nq -> next);
                nq -> max = p -> max + 1;
                nq -> modify(q -> fa);
                q -> modify(nq);
                np -> modify(nq);
                for( ; p && p -> next[w] == q; p = p -> fa)
                    p -> next[w] = nq;
            }
        }
    }
    inline void decodewithmask(R int mask)
    {
        scanf("%s", str);
        R int len = strlen(str);
        for (R int i = 0; i < len; ++i)
        {
            mask = (mask * 131 + i) % len;
            R char tmp = str[i];
            str[i] = str[mask];
            str[mask] = tmp;
        }
    }
    inline int query()
    {
        R sam *p = sam_mem;
        R int l = strlen(str);
        for (R int i = 0; i < l && p; ++i)
            p = p -> next[str[i] - 'A'];
        return p ? p -> query() : 0;
    }
    char opt[maxn];
    int main()
    {
    //  setfile();
        null = mem; head = sam_mem;
        null -> fa = null -> ch[0] = null -> ch[1] = null; null -> sum = null -> val = 0;
        mem[1] = mem[0];
        R int n, len, mask = 0;
        scanf("%d", &n);
        scanf("%s", str + 1);
        len = strlen(str + 1);
        for (R int i = 1; i <= len; ++i) extend(str[i] - 'A');
        for (R int i = 1; i <= n; ++i)
        {
            scanf("%s", opt);
            decodewithmask(mask);
            if (opt[0] == 'Q')
            {
                R int ans = query();
                printf("%d
    ", ans );
                mask ^= ans;
            }
            else
            {
                R int l = strlen(str);
                for (R int i = 0; i < l; ++i)
                    extend(str[i] - 'A');
            }
        }
        return 0;
    }
    /*
    2
    A
    QUERY B
    ADD BBABBBBAAB
    */
  • 相关阅读:
    07. pt-fifo-split
    05. pt-diskstats
    06. pt-duplicate-key-checker
    坑爹的tp-link管理密码设置
    windows核心编程 第5章job lab示例程序 解决小技巧
    FormatMessage将错误代码转换成对应的字符串
    调试 内存查看StringCchCopy的运行前后
    对硬盘扇区的操作,练手代码
    关不掉的窗口
    读取unicode日志文件并清除记录的垃圾文件
  • 原文地址:https://www.cnblogs.com/cocottt/p/6764996.html
Copyright © 2011-2022 走看看