签到提;
题意:求出每一个回文串的贡献 (贡献的计算就是回文串不同字符的个数)
题解:
用回文树直接暴力即可
回文树开一个数组cost[ ][26] 和val[ ] 数组;
val【i】表示回文树上节点 i 的对应的回文的贡献
最后统计答案即可
LL get_ans() { LL ans = 0; for (int i = sz - 1; i >= 0; --i) ans += 1LL * cnt[i] * val[i]; return ans;}
1 #include <set> 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include <string> 9 #include 10 #include 11 #include 12 #include 13 #include 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("******\n") 22 #define mem(a, b) memset(a,b,sizeof(a)) 23 #define name2str(x) #x 24 #define fuck(x) cout<<#x" = "< 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 = 4e5 + 7; 49 const int maxm = 8e6 + 10; 50 const int INF = 0x3f3f3f3f; 51 const int mod = 1e9 + 7; 52 char s[maxn]; 53 54 struct Palindrome_Automaton { 55 int len[maxn], next[maxn][26], fail[maxn], cnt[maxn], cost[maxn][26], val[maxn]; 56 int num[maxn], S[maxn], sz, n, last; 57 58 int newnode(int l) { 59 for (int i = 0; i < 26; ++i)next[sz][i] = 0, cost[sz][i] = 0; 60 cnt[sz] = num[sz] = 0, len[sz] = l; 61 return sz++; 62 } 63 64 void init() { 65 sz = n = last = 0; 66 newnode(0); 67 newnode(-1); 68 S[0] = -1; 69 fail[0] = 1; 70 } 71 72 int get_fail(int x) { 73 while (S[n - len[x] - 1] != S[n])x = fail[x]; 74 return x; 75 } 76 77 void add(int c, int pos) { 78 c -= 'a'; 79 S[++n] = c; 80 int cur = get_fail(last); 81 if (!next[cur][c]) { 82 int now = newnode(len[cur] + 2); 83 fail[now] = next[get_fail(fail[cur])][c]; 84 next[cur][c] = now; 85 num[now] = num[fail[now]] + 1; 86 87 for (int i = 0; i < 26; i++) cost[now][i] = cost[cur][i]; 88 cost[now][c] = 1; 89 int temp = 0; 90 for (int i = 0; i < 26; i++) temp += cost[now][i]; 91 val[now] = temp; 92 93 } 94 last = next[cur][c]; 95 cnt[last]++; 96 } 97 98 void count()//统计本质相同的回文串的出现次数 99 { 100 for (int i = sz - 1; i >= 0; --i)cnt[fail[i]] += cnt[i]; 101 //逆序累加,保证每个点都会比它的父亲节点先算完,于是父亲节点能加到所有子孙 102 } 103 104 LL get_ans() { 105 LL ans = 0; 106 for (int i = sz - 1; i >= 0; --i) ans += 1LL * cnt[i] * val[i]; 107 return ans; 108 } 109 } pam; 110 111 int main() { 112 FIN; 113 sfs(s + 1); 114 pam.init(); 115 int n = strlen(s + 1); 116 for (int i = 1; i <= n; i++) { 117 pam.add(s[i], i); 118 } 119 pam.count(); 120 LL ans = pam.get_ans(); 121 printf("%lld\n", ans); 122 return 0; 123 }