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