题意:
有n种操作,开始给你一个空串,给你4中操作
1 c 在字符串的首部添加字符c
2 c 在字符串的尾部添加字符c
3 询问字符中的本质不同的回文串的个数
4 询问字符串中回文串的个数
思路:last[0]表示首部的操作的位置,last[1]表示尾部的操作的位置
模板提,用上双向的回文树就好了。
1 #include <set> 2 #include <map> 3 #include <stack> 4 #include <queue> 5 #include <cmath> 6 #include <ctime> 7 #include <cstdio> 8 #include <string> 9 #include <vector> 10 #include <cstring> 11 #include <iostream> 12 #include <algorithm> 13 #include <unordered_map> 14 15 #define pi acos(-1.0) 16 #define eps 1e-9 17 #define fi first 18 #define se second 19 #define rtl rt<<1 20 #define rtr rt<<1|1 21 #define bug printf("****** ") 22 #define mem(a, b) memset(a,b,sizeof(a)) 23 #define name2str(x) #x 24 #define fuck(x) cout<<#x" = "<<x<<endl 25 #define sfi(a) scanf("%d", &a) 26 #define sffi(a, b) scanf("%d %d", &a, &b) 27 #define sfffi(a, b, c) scanf("%d %d %d", &a, &b, &c) 28 #define sffffi(a, b, c, d) scanf("%d %d %d %d", &a, &b, &c, &d) 29 #define sfL(a) scanf("%lld", &a) 30 #define sffL(a, b) scanf("%lld %lld", &a, &b) 31 #define sfffL(a, b, c) scanf("%lld %lld %lld", &a, &b, &c) 32 #define sffffL(a, b, c, d) scanf("%lld %lld %lld %lld", &a, &b, &c, &d) 33 #define sfs(a) scanf("%s", a) 34 #define sffs(a, b) scanf("%s %s", a, b) 35 #define sfffs(a, b, c) scanf("%s %s %s", a, b, c) 36 #define sffffs(a, b, c, d) scanf("%s %s %s %s", a, b,c, d) 37 #define FIN freopen("../in.txt","r",stdin) 38 #define gcd(a, b) __gcd(a,b) 39 #define lowbit(x) x&-x 40 #define IO iOS::sync_with_stdio(false) 41 42 43 using namespace std; 44 typedef long long LL; 45 typedef unsigned long long ULL; 46 const ULL seed = 13331; 47 const LL INFLL = 0x3f3f3f3f3f3f3f3fLL; 48 const int maxn = 1e5 + 7; 49 const int maxm = 8e6 + 10; 50 const int INF = 0x3f3f3f3f; 51 const int mod = 1e9 + 7; 52 char s[maxn]; 53 LL sum[maxn]; 54 55 struct Palindrome_Automaton { 56 int len[maxn * 2], next[maxn * 2][26], fail[maxn * 2], cnt[maxn * 2]; 57 int num[maxn * 2], S[maxn * 2], sz, n[2], last[2]; 58 59 int newnode(int l) { 60 for (int i = 0; i < 26; ++i)next[sz][i] = 0; 61 cnt[sz] = num[sz] = 0, len[sz] = l; 62 return sz++; 63 } 64 65 void init() { 66 sz = 0; 67 newnode(0); 68 newnode(-1); 69 S[0] = -1; 70 fail[0] = 1; 71 last[0] = last[1] = 0; 72 n[0] = maxn - 7, n[1] = maxn - 8; 73 } 74 75 int get_fail(int x, int k) { 76 S[n[0] - 1] = -1, S[n[1] + 1] = -1; 77 while (S[n[k] - (k ? 1 : -1) * (len[x] + 1)] != S[n[k]])x = fail[x]; 78 return x; 79 } 80 81 int add(int c, int k) { 82 c -= 'a'; 83 S[n[k] += (k ? 1 : -1)] = c; 84 int cur = get_fail(last[k],k); 85 if (!(last[k] = next[cur][c])) { 86 int now = newnode(len[cur] + 2); 87 fail[now] = next[get_fail(fail[cur],k)][c]; 88 next[cur][c] = now; 89 num[now] = num[fail[now]] + 1; 90 last[k]=now; 91 if (len[last[k]]==n[1]-n[0]+1) last[k^1]=last[k]; 92 } 93 //last[k] = next[cur][c]; 94 //cnt[last]++; 95 return num[last[k]]; 96 } 97 98 void count()//统计本质相同的回文串的出现次数 99 { 100 for (int i = sz - 1; i >= 0; --i)cnt[fail[i]] += cnt[i]; 101 //逆序累加,保证每个点都会比它的父亲节点先算完,于是父亲节点能加到所有子孙 102 } 103 } pam; 104 char op[10]; 105 int n; 106 int main() { 107 //FIN; 108 while(~sfi(n)){ 109 pam.init(); 110 LL ans=0; 111 for (int i = 0,x; i < n; ++i) { 112 sfi(x); 113 if (x==1) { 114 sfs(op); 115 ans+=pam.add(op[0],0); 116 }else if (x==2) { 117 sfs(op); 118 ans+=pam.add(op[0],1); 119 }else if (x==3) printf("%d ",pam.sz-2); 120 else printf("%lld ",ans); 121 } 122 } 123 return 0; 124 }