板子们~

要省选啦!码码板子…… 

const int N = 200010;
char st[N];
int rk[N], sa[N], nr[N], ns[N], tab[N], hi[N];
void calc(int n)
{
    for (int i = 0; i <= 26; ++ i) tab[i] = 0;
    for (int i = 1; i <= n; ++ i) tab[st[i] - 'a' + 1] = 1;
    for (int i = 1; i <= 26; ++ i) tab[i] += tab[i - 1];
    for (int i = 1; i <= n; ++ i) rk[i] = tab[st[i] - 'a' + 1];
    for (int p = 2; (p >> 1) <= n; p <<= 1)
    {
        for (int i = 0; i <= n; ++ i) tab[i] = 0;
        for (int i = 1; i <= n; ++ i) tab[rk[i + (p >> 1)]] ++;
        for (int i = 1; i <= n; ++ i) tab[i] += tab[i - 1];
        for (int i = n; i >= 1; -- i) ns[tab[rk[i + (p >> 1)]] --] = i;
        for (int i = 0; i <= n; ++ i) tab[i] = 0;
        for (int i = 1; i <= n; ++ i) tab[rk[i]] ++;
        for (int i = 1; i <= n; ++ i) tab[i] += tab[i - 1];
        for (int i = n; i >= 1; -- i) sa[tab[rk[ns[i]]] --] = ns[i];
        nr[sa[1]] = 1;
        for (int i = 2; i <= n; ++ i)
            if (rk[sa[i]] == rk[sa[i - 1]] && rk[sa[i] + (p >> 1)] == rk[sa[i - 1] + (p >> 1)])
                nr[sa[i]] = nr[sa[i - 1]];
            else
                nr[sa[i]] = nr[sa[i - 1]] + 1;
        for (int i = 1; i <= n; ++ i)
            rk[i] = nr[i];
        if (rk[sa[n]] == n) break;
    }
    for (int i = 1; i <= n; ++ i)
        if (rk[i] != 1)
        {
            hi[rk[i]] = max(hi[rk[i - 1]] - 1, 0);
            while (st[i + hi[rk[i]]] == st[sa[rk[i] - 1] + hi[rk[i]]])
                hi[rk[i]] ++;
        }
}
SA

这个SA奇满无比…… 但至少能用?

const int N = 200000;
int nxt[N][30], par[N], len[N], tot;
int append(int p, int c)
{
    if (nxt[p][c] && len[nxt[p][c]] == len[p] + 1) return nxt[p][c];
    int np = ++ tot, f = nxt[p][c]; len[np] = len[p] + 1;
    while (p && !nxt[p][c]) nxt[p][c] = np, p = par[p];
    if (!p) par[np] = 1;
    else
    {
        int q = nxt[p][c];
        if (len[q] == len[p] + 1) par[np] = q;
        else
        {
            int nq = f ? np : ++ tot;
            len[nq] = len[p] + 1;
            memcpy(nxt[nq], nxt[q], sizeof(nxt[q]));
            par[nq] = par[q]; par[q] = nq; if (!f) par[np] = nq;
            while (p && nxt[p][c] == q) nxt[p][c] = nq, p = par[p];
        }
    }
    return np;
}
SAM

这个SAM应该是真的SAM!建在trie树上不会有无用节点~

const int N = 200000;
char st[N]; int n, len[N];
void manacher(int n)
{
    int md = 0, mx = 0;
    for (int i = 1; i <= n; ++ i)
    {
        if (mx >= i) len[i] = min(mx - i, len[md * 2 - i]);
        while (st[i + len[i]] == st[i - len[i]]) len[i] ++;
        if (i + len[i] > mx) mx = i + len[i], md = i;
    }
}
manacher

马拉车~

const int N = 200000;
char st[N];
int nxt[N][30], par[N], len[N], n, tot, p;
int append(int p, int c, int i)
{
    while (st[i] != st[i - len[p] - 1]) p = par[p];
    if (!nxt[p][c])
    {
        int np = nxt[p][c] = ++ tot;
        len[np] = len[p] + 2;
        int q = par[p];
        while (q && !nxt[q][c]) q = par[q];
        if (!q) par[np] = 2;
        else par[np] = nxt[q][c];
    }
    return nxt[p][c];
}
eertree

PAM好像非常短的样子呢

const int N = 200000;
char st[N]; int n;
int calc(int n)
{
    int i = 1, j = 2, k = 0;
    for (; i <= n && j <= n && k < n; )
    {
        int si = st[i + k > n ? i + k - n : i + k],
            sj = st[j + k > n ? j + k - n : j + k];
        if (si == sj) k ++;
        else
        {
            if (si < sj) j += k + 1;
            else i += k + 1;
            k = 0;
            if (i == j) j ++;
        }
    }
    return min(i, j);
}
minRepr

以前从来没有写过最小表示法QAQ

好像都是字符串算法,补一些其他的东西吧

struct treap
{
    treap *left, *right;
    int siz, val;

treap ()
{
    left = right = NULL; siz = val = 0;
}

treap *update()
{
    this->siz = 1;
    if (this->left != NULL) this->siz += this->left->siz;
    if (this->right != NULL) this->siz += this->right->siz;
    return this;
}

treap *push_down()
{
    return this;
}

treap *append(treap *p)
{
    this->siz += p->siz;
    return this;
}

};

treap *join(treap *t1, treap *t2)
{
    if (t1 == NULL) return t2;
    if (t2 == NULL) return t1;
    if (rand() % (t1->siz + t2->siz) < t1->siz)
    {
        t1->push_down();
        t1->right = join(t1->right, t2);
        return t1->update();
    }
    else
    {
        t2->push_down();
        t2->left = join(t1, t2->left);
        return t2->update();
    }
}

auto split(treap *t, treap *p)
{
    if (t == NULL)
        return make_pair((treap*)NULL, (treap*)NULL);
    t->push_down();
    if (p->val < t->val)
    {
        auto f = split(t->left, p);
        t->left = f.second;
        return make_pair(f.first, t->update());
    }
    else
    {
        auto f = split(t->right, p);
        t->right = f.first;
        return make_pair(t->update(), f.second);
    }
}

treap *insert(treap *t, treap *p)
{
    if (t == NULL || rand() % (t->siz + 1) == 0)
    {
        auto f = split(t, p);
        p->left = f.first; p->right = f.second;
        return p->update();
    }
    else
    {
        t->push_down();
        if (p->val < t->val)
            t->left = insert(t->left, p);
        else
            t->right = insert(t->right, p);
        return t->append(p);
    }
}

treap *erase(treap *t, treap *p)
{
    if (t == NULL) return NULL;
    t->push_down();
    if (t->val == p->val)
        return join(t->left, t->right);
    else if (p->val < t->val)
        t->left = erase(t->left, p);
    else
        t->right = erase(t->right, p);
    return t->update();
}

treap *merge(treap *t1, treap *t2)
{
    if (t1 == NULL) return t2;
    if (t2 == NULL) return t1;
    if (rand() % (t1->siz + t2->siz) < t2->siz)
        swap(t1, t2);
    auto f = split(t2, t1);
    t1->push_down();
    t1->left = merge(t1->left, f.first);
    t1->right = merge(t1->right, f.second);
    return t1->update();
}
treap

一棵非常优秀的二叉排序树,可以在上面套其他数据结构!(不过二叉排序树上怎么套东西?

posted @ 2018-03-20 20:00  AwD!  阅读(561)  评论(0编辑  收藏  举报