【回文自动机】 HDU 5421 Victor and String
题意:首尾加字符,询问多少个本质不同的回文串和多少个不同回文串
思路:标记即可,分别维护左右last指针
代码:
#include <cstdio> #include <cstring> typedef long long ll; template <class T> inline bool rd(T &ret) { char c; int sgn; if(c = getchar() , c == EOF) return false; while(c != '-' && (c < '0' || c > '9')) c = getchar(); sgn = (c == '-') ? -1 : 1; ret = (c == '-') ? 0 : (c - '0'); while(c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0'); ret *= sgn; return true; } const int MAX_N = 600005; const int SIG = 26; int n; struct PTree { int nxt[MAX_N][SIG], fail[MAX_N], cnt[MAX_N], num[MAX_N], len[MAX_N], S[MAX_N]; int last[2], L, R, p; ll tot; int newNode (int l) { memset(nxt[p], 0, sizeof nxt[p]); cnt[p] = num[p] = 0; len[p] = l; return p++; } void init() { p = tot = 0; newNode(0), newNode(-1); L = n, R = n - 1; for (int i = 0; i < 2 * n; ++i) S[i] = -1; last[0] = last[1] = 1; fail[0] = 1; } int getFail(int x, bool d) { if (d) while (S[R - len[x] - 1] != S[R]) x = fail[x]; else while (S[L + len[x] + 1] != S[L]) x = fail[x]; return x; } void add(int c, bool d) { c = c - 'a'; if (d) S[++R] = c; else S[--L] = c; int cur = getFail(last[d], d); if (!nxt[cur][c]) { int now = newNode(len[cur] + 2); fail[now] = nxt[getFail(fail[cur], d)][c]; nxt[cur][c] = now; num[now] = num[fail[now]] + 1; } last[d] = nxt[cur][c]; if (len[last[d]] == R - L + 1) last[d ^ 1] = last[d]; tot += num[last[d]]; } }; PTree T; char str[2]; int main() { while (1 == scanf("%d", &n)) { T.init(); while (n-- > 0) { int opt;rd(opt); if (opt < 3) scanf("%s", str), T.add(str[0], opt - 1); else if (opt == 3) printf("%d\n", T.p - 2); else printf("%I64d\n", T.tot); } } return 0; }