Loading [MathJax]/extensions/tex2jax.js

BZOJ2555:SubString – 题解

主要思路

为啥我看到了 C# 代码(那是我逝去的青春)

首先知道肯定是 SAM,但是你我都知道在线性构造的时候树的形态会变,所以没法维护根点权值和。所以加上一个 LCT 弄一下即可。

代码

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// BZ2555.cpp
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 6010000;
int q, mask, ch[MAX_N << 1][2], fa[MAX_N << 1], siz[MAX_N << 1], tag[MAX_N << 1], ptot = 1, last_ptr = 1;
char str[MAX_N], cmdlet[5];
struct node
{
int ch[26], dep, link;
} nodes[MAX_N];
#define lson (ch[p][0])
#define rson (ch[p][1])
// LCT;
bool isRoot(int p) { return ch[fa[p]][0] != p && ch[fa[p]][1] != p; }
int check(int p) { return ch[fa[p]][1] == p; }
void rotate(int x)
{
int y = fa[x], z = fa[y], dir = check(x), w = ch[x][dir ^ 1];
fa[x] = z;
if (!isRoot(y))
ch[z][check(y)] = x;
fa[y] = x, ch[x][dir ^ 1] = y;
fa[w] = y, ch[y][dir] = w;
}
void pushdown(int p)
{
if (tag[p])
{
siz[lson] += tag[p], siz[rson] += tag[p];
tag[lson] += tag[p], tag[rson] += tag[p];
tag[p] = 0;
}
}
void update(int p)
{
if (!isRoot(p))
update(fa[p]);
pushdown(p);
}
void splay(int p)
{
update(p);
for (int fat = fa[p]; fat = fa[p], !isRoot(p); rotate(p))
if (!isRoot(fat))
rotate(check(fat) == check(p) ? fat : p);
}
void access(int p)
{
for (int pre = 0; p; pre = p, p = fa[p])
splay(p), rson = pre;
}
void link(int x, int y) { fa[x] = y, access(y), splay(y), tag[y] += siz[x], siz[y] += siz[x]; }
void cut(int x) { access(x), splay(x), tag[ch[x][0]] -= siz[x], siz[ch[x][0]] -= siz[x], ch[x][0] = fa[ch[x][0]] = 0; }
#undef rson
#undef lson
void insert(int c)
{
int pre = last_ptr, p = last_ptr = ++ptot;
nodes[p].dep = nodes[pre].dep + 1, siz[p] = 1;
while (pre && nodes[pre].ch[c] == 0)
nodes[pre].ch[c] = p, pre = nodes[pre].link;
if (pre == 0)
nodes[p].link = 1, link(p, 1);
else
{
int q = nodes[pre].ch[c];
if (nodes[q].dep == nodes[pre].dep + 1)
nodes[p].link = q, link(p, q);
else
{
int clone = ++ptot;
nodes[clone] = nodes[q], nodes[clone].dep = nodes[pre].dep + 1;
cut(q), nodes[p].link = nodes[q].link = clone, link(p, clone), link(q, clone), link(clone, nodes[clone].link);
while (pre && nodes[pre].ch[c] == q)
nodes[pre].ch[c] = clone, pre = nodes[pre].link;
}
}
}
void decode()
{
int len = strlen(str), tmp = mask;
for (int i = 0; i < len; i++)
tmp = (tmp * 131 + i) % len, swap(str[i], str[tmp]);
}
int main()
{
scanf("%d%s", &q, str);
for (int i = 0; str[i]; i++)
insert(str[i] - 'A');
while (q--)
{
scanf("%s%s", cmdlet, str), decode();
if (cmdlet[0] == 'A')
for (int i = 0; str[i]; i++)
insert(str[i] - 'A');
else
{
int p = 1;
bool flag = true;
for (int i = 0; str[i]; i++)
if (nodes[p].ch[str[i] - 'A'])
p = nodes[p].ch[str[i] - 'A'];
else
{
puts("0"), flag = false;
break;
}
if (flag)
splay(p), printf("%d\n", siz[p]), mask ^= siz[p];
}
}
return 0;
}
// BZ2555.cpp #include <bits/stdc++.h> using namespace std; const int MAX_N = 6010000; int q, mask, ch[MAX_N << 1][2], fa[MAX_N << 1], siz[MAX_N << 1], tag[MAX_N << 1], ptot = 1, last_ptr = 1; char str[MAX_N], cmdlet[5]; struct node { int ch[26], dep, link; } nodes[MAX_N]; #define lson (ch[p][0]) #define rson (ch[p][1]) // LCT; bool isRoot(int p) { return ch[fa[p]][0] != p && ch[fa[p]][1] != p; } int check(int p) { return ch[fa[p]][1] == p; } void rotate(int x) { int y = fa[x], z = fa[y], dir = check(x), w = ch[x][dir ^ 1]; fa[x] = z; if (!isRoot(y)) ch[z][check(y)] = x; fa[y] = x, ch[x][dir ^ 1] = y; fa[w] = y, ch[y][dir] = w; } void pushdown(int p) { if (tag[p]) { siz[lson] += tag[p], siz[rson] += tag[p]; tag[lson] += tag[p], tag[rson] += tag[p]; tag[p] = 0; } } void update(int p) { if (!isRoot(p)) update(fa[p]); pushdown(p); } void splay(int p) { update(p); for (int fat = fa[p]; fat = fa[p], !isRoot(p); rotate(p)) if (!isRoot(fat)) rotate(check(fat) == check(p) ? fat : p); } void access(int p) { for (int pre = 0; p; pre = p, p = fa[p]) splay(p), rson = pre; } void link(int x, int y) { fa[x] = y, access(y), splay(y), tag[y] += siz[x], siz[y] += siz[x]; } void cut(int x) { access(x), splay(x), tag[ch[x][0]] -= siz[x], siz[ch[x][0]] -= siz[x], ch[x][0] = fa[ch[x][0]] = 0; } #undef rson #undef lson void insert(int c) { int pre = last_ptr, p = last_ptr = ++ptot; nodes[p].dep = nodes[pre].dep + 1, siz[p] = 1; while (pre && nodes[pre].ch[c] == 0) nodes[pre].ch[c] = p, pre = nodes[pre].link; if (pre == 0) nodes[p].link = 1, link(p, 1); else { int q = nodes[pre].ch[c]; if (nodes[q].dep == nodes[pre].dep + 1) nodes[p].link = q, link(p, q); else { int clone = ++ptot; nodes[clone] = nodes[q], nodes[clone].dep = nodes[pre].dep + 1; cut(q), nodes[p].link = nodes[q].link = clone, link(p, clone), link(q, clone), link(clone, nodes[clone].link); while (pre && nodes[pre].ch[c] == q) nodes[pre].ch[c] = clone, pre = nodes[pre].link; } } } void decode() { int len = strlen(str), tmp = mask; for (int i = 0; i < len; i++) tmp = (tmp * 131 + i) % len, swap(str[i], str[tmp]); } int main() { scanf("%d%s", &q, str); for (int i = 0; str[i]; i++) insert(str[i] - 'A'); while (q--) { scanf("%s%s", cmdlet, str), decode(); if (cmdlet[0] == 'A') for (int i = 0; str[i]; i++) insert(str[i] - 'A'); else { int p = 1; bool flag = true; for (int i = 0; str[i]; i++) if (nodes[p].ch[str[i] - 'A']) p = nodes[p].ch[str[i] - 'A']; else { puts("0"), flag = false; break; } if (flag) splay(p), printf("%d\n", siz[p]), mask ^= siz[p]; } } return 0; }
// BZ2555.cpp
#include <bits/stdc++.h>

using namespace std;

const int MAX_N = 6010000;

int q, mask, ch[MAX_N << 1][2], fa[MAX_N << 1], siz[MAX_N << 1], tag[MAX_N << 1], ptot = 1, last_ptr = 1;
char str[MAX_N], cmdlet[5];

struct node
{
    int ch[26], dep, link;
} nodes[MAX_N];

#define lson (ch[p][0])
#define rson (ch[p][1])

// LCT;

bool isRoot(int p) { return ch[fa[p]][0] != p && ch[fa[p]][1] != p; }

int check(int p) { return ch[fa[p]][1] == p; }

void rotate(int x)
{
    int y = fa[x], z = fa[y], dir = check(x), w = ch[x][dir ^ 1];
    fa[x] = z;
    if (!isRoot(y))
        ch[z][check(y)] = x;
    fa[y] = x, ch[x][dir ^ 1] = y;
    fa[w] = y, ch[y][dir] = w;
}

void pushdown(int p)
{
    if (tag[p])
    {
        siz[lson] += tag[p], siz[rson] += tag[p];
        tag[lson] += tag[p], tag[rson] += tag[p];
        tag[p] = 0;
    }
}

void update(int p)
{
    if (!isRoot(p))
        update(fa[p]);
    pushdown(p);
}

void splay(int p)
{
    update(p);
    for (int fat = fa[p]; fat = fa[p], !isRoot(p); rotate(p))
        if (!isRoot(fat))
            rotate(check(fat) == check(p) ? fat : p);
}

void access(int p)
{
    for (int pre = 0; p; pre = p, p = fa[p])
        splay(p), rson = pre;
}

void link(int x, int y) { fa[x] = y, access(y), splay(y), tag[y] += siz[x], siz[y] += siz[x]; }

void cut(int x) { access(x), splay(x), tag[ch[x][0]] -= siz[x], siz[ch[x][0]] -= siz[x], ch[x][0] = fa[ch[x][0]] = 0; }

#undef rson
#undef lson

void insert(int c)
{
    int pre = last_ptr, p = last_ptr = ++ptot;
    nodes[p].dep = nodes[pre].dep + 1, siz[p] = 1;
    while (pre && nodes[pre].ch[c] == 0)
        nodes[pre].ch[c] = p, pre = nodes[pre].link;
    if (pre == 0)
        nodes[p].link = 1, link(p, 1);
    else
    {
        int q = nodes[pre].ch[c];
        if (nodes[q].dep == nodes[pre].dep + 1)
            nodes[p].link = q, link(p, q);
        else
        {
            int clone = ++ptot;
            nodes[clone] = nodes[q], nodes[clone].dep = nodes[pre].dep + 1;
            cut(q), nodes[p].link = nodes[q].link = clone, link(p, clone), link(q, clone), link(clone, nodes[clone].link);
            while (pre && nodes[pre].ch[c] == q)
                nodes[pre].ch[c] = clone, pre = nodes[pre].link;
        }
    }
}

void decode()
{
    int len = strlen(str), tmp = mask;
    for (int i = 0; i < len; i++)
        tmp = (tmp * 131 + i) % len, swap(str[i], str[tmp]);
}

int main()
{
    scanf("%d%s", &q, str);
    for (int i = 0; str[i]; i++)
        insert(str[i] - 'A');
    while (q--)
    {
        scanf("%s%s", cmdlet, str), decode();
        if (cmdlet[0] == 'A')
            for (int i = 0; str[i]; i++)
                insert(str[i] - 'A');
        else
        {
            int p = 1;
            bool flag = true;
            for (int i = 0; str[i]; i++)
                if (nodes[p].ch[str[i] - 'A'])
                    p = nodes[p].ch[str[i] - 'A'];
                else
                {
                    puts("0"), flag = false;
                    break;
                }
            if (flag)
                splay(p), printf("%d\n", siz[p]), mask ^= siz[p];
        }
    }
    return 0;
}

 

Leave a Reply

Your email address will not be published. Required fields are marked *