UESTC - 1999 也许这是唯一能阻止乐爷AK的方法( Just for Fun )(回文树)

https://vjudge.net/problem/UESTC-1999

题意

对于一个初始为空的字符串S,你可以进行以下两种操作:

1. 在S的末尾加一个小写字母。

2. 移除S的最后一个字母。

每进行完一个操作,你需要统计S中回文串的数量。

分析

模板题,每次跑一遍回文树

#include<cstdio>
#include<string.h>
#include<cstring>
#include<string>
using namespace std; const int MAXN = 1e4 + ;
const int N = ; const int maxn = 1e4 + ;
const int ALP = ; struct PAM {
int next[maxn][ALP];
int fail[maxn];
int cnt[maxn];
int num[maxn];
int len[maxn];
int s[maxn];
int last, n, p; int newnode(int l) {
for (int i = ; i<ALP; i++)
next[p][i] = ;
cnt[p] = num[p] = ;
len[p] = l;
return p++;
}
void init() {
p = ;
newnode();
newnode(-);
last = ;
n = ;
s[n] = -;
fail[] = ;
}
int get_fail(int x) {
while (s[n - len[x] - ] != s[n]) x = fail[x];
return x;
}
void add(int c) {
c = c - 'a';
s[++n] = c;
int cur = get_fail(last);
if (!next[cur][c]) {
int now = newnode(len[cur] + );
fail[now] = next[get_fail(fail[cur])][c];
next[cur][c] = now;
num[now] = num[fail[now]] + ;
}
last = next[cur][c];
cnt[last]++;
}
void count() {
for (int i = p - ; i >= ; i--)
cnt[fail[i]] += cnt[i];
}
}tree; char s[MAXN];
string snew;
int q, ans[MAXN]; int main() {
scanf("%d", &q);
scanf("%s", s);
for (int i = ; i < q; i++) {
if (s[i] == '-') snew.pop_back();
else snew.push_back(s[i]);
tree.init();
for (int j = ; j < snew.size(); j++) {
tree.add(snew[j]);
}
tree.count();
for (int j = ; j < tree.p; j++) {
ans[i] += tree.cnt[j];
}
}
for (int i = ; i < q; i++) {
printf("%d ", ans[i]);
}
return ;
}
上一篇:php语法同java语法的基本区别(实例项目需求,php才能熟)


下一篇:cf1020c 瞎搞