【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\n", 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
*/
posted @ 2016-06-17 11:47  cot  阅读(172)  评论(0编辑  收藏  举报