Victor and String[Bestcoder #52 1004](回文树)

Posted zcr-blog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Victor and String[Bestcoder #52 1004](回文树)相关的知识,希望对你有一定的参考价值。

题目描述

Victor喜欢玩字符串。他认为一个字符串是迷人的,当且仅当字符串是回文的。
Victor想玩n次。每次他都会做以下四种操作中的一种。
操作1:在字符串的开头添加一个字符 c。
操作2:在字符串的末尾添加一个字符 c。
操作3:询问不同的迷人子字符串的数量。
操作4:询问迷人子字符串的数量,必须计算从不同位置开始的相同子字符串的数量。
在一开始Victor有一个空字符串。

输入格式

输入包含几个测试用例,最多5个用例。 在每个测试用例中,第一行一个整数n表示操作的数量。
下面n行的第一个数字是整数op,表示操作的类型。如果op=1或2,后面会有一个小写的英文字母。

输出格式

对于每个查询操作(操作3或4),输出正确的答案。

样例

输入样例1

6
1 a
1 b
2 a
2 c
3
4
8
1 a
2 a
2 a
1 a
3
1 b
3
4

输出样例2

4
5
4
5
11

这是一道模板题,直接上代码。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int N = 400000;
struct Plalindrome_Tree{
    int go[26], len, fail;
    ll fail_len;
}pt[N];
int pre, suf, tot;
ll ans;
int q;
int l, r;
char s[N];
void init() {
    memset(s, -1, sizeof(s));
    memset(pt, 0, sizeof(pt));
    tot = ans = 0;
    pre = suf = 0;
    l = 200000;
    r = 199999;
}
void build() {
    pt[++tot].len = -1;
    pt[0].fail = pt[1].fail = 1;
    pt[0].fail_len = 2;
    pt[1].fail_len = 1;
}
void add_back(int c) {
    int p = suf;
    while (s[r - pt[p].len - 1] != s[r]) p = pt[p].fail;
    if (!pt[p].go[c]) {
        int v = ++tot, k = pt[p].fail;
        pt[v].len = pt[p].len + 2;
        while (s[r - pt[k].len - 1] != s[r]) k = pt[k].fail;
        pt[v].fail = pt[k].go[c];
        pt[v].fail_len = pt[pt[k].go[c]].fail_len + 1;
        pt[p].go[c] = v;
    }
    suf = pt[p].go[c];
}
void add_front(int c) {
    int p = pre;
    while (s[l + pt[p].len + 1] != s[l]) p = pt[p].fail;
    if (!pt[p].go[c]) {
        int v = ++tot, k = pt[p].fail;
        pt[v].len = pt[p].len + 2;
        while (s[l + pt[k].len + 1] != s[l]) k = pt[k].fail;
        pt[v].fail = pt[k].go[c];
        pt[v].fail_len = pt[pt[k].go[c]].fail_len + 1;
        pt[p].go[c] = v;
    }
    pre = pt[p].go[c];
}
int main() {
    while (cin >> q) {
        init();
        build();
        while (q--) {
            int opt;
            char ch;
            cin >> opt;
            switch (opt) {
                case 1:
                    cin >> ch;
                    s[--l] = ch;
                    add_front(ch - a);
                    ans += pt[pre].fail_len - 2;
                    if (pt[pre].len == r - l + 1) suf = pre;
                    break;
                case 2:
                    cin >> ch;
                    s[++r] = ch;
                    add_back(ch - a);
                    ans += pt[suf].fail_len - 2;
                    if (pt[suf].len == r - l + 1) pre = suf;
                    break;
                case 3:
                    cout << tot - 1;
                    puts("");
                    break;
                case 4:
                    cout << ans;
                    puts("");
                    break;
                default:
                    puts("Wrong Input");
                    break;
            }
        }

    }
    return 0;
}

以上是关于Victor and String[Bestcoder #52 1004](回文树)的主要内容,如果未能解决你的问题,请参考以下文章

HDOJ 5421 Victor and String 回文串自己主动机

HDU - 5421:Victor and String (回文树,支持首尾插入新字符)

codeforces 460D:Little Victor and Set

HDU 5418 Victor and World 允许多次经过的TSP

HDOJ 5418 Victor and World 状压DP

Codeforces 460 D. Little Victor and Set