题意:
记录不相交的回文串对数
题解:
正着反着都来一遍回文树
用sum1【i】 表示到 i 位置,出现的回文串个数的前缀和
sun2【i】表示反着的个数
ans+=sum1【i-1】*sum2【i】
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 = 1e6 + 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], next[maxn][26], fail[maxn], cnt[maxn]; 57 int num[maxn], S[maxn], sz, n, last; 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 = n = last = 0; 67 newnode(0); 68 newnode(-1); 69 S[0] = -1; 70 fail[0] = 1; 71 } 72 73 int get_fail(int x) { 74 while (S[n - len[x] - 1] != S[n])x = fail[x]; 75 return x; 76 } 77 78 void add(int c, int pos) { 79 c -= 'a'; 80 S[++n] = c; 81 int cur = get_fail(last); 82 if (!next[cur][c]) { 83 int now = newnode(len[cur] + 2); 84 fail[now] = next[get_fail(fail[cur])][c]; 85 next[cur][c] = now; 86 num[now] = num[fail[now]] + 1; 87 } 88 last = next[cur][c]; 89 cnt[last]++; 90 } 91 92 void count()//统计本质相同的回文串的出现次数 93 { 94 for (int i = sz - 1; i >= 0; --i)cnt[fail[i]] += cnt[i]; 95 //逆序累加,保证每个点都会比它的父亲节点先算完,于是父亲节点能加到所有子孙 96 } 97 } pam; 98 99 int main() { 100 // FIN; 101 while (~sfs(s + 1)) { 102 pam.init(); 103 int n = strlen(s + 1); 104 for (int i = 1; i <= n; i++) { 105 pam.add(s[i], i); 106 sum[i] = sum[i - 1] + pam.num[pam.last]; 107 } 108 pam.init(); 109 LL ans = 0; 110 for (int i = n; i >= 1; --i) { 111 pam.add(s[i], i); 112 ans += pam.num[pam.last] * sum[i - 1]; 113 } 114 printf("%lld\n", ans); 115 } 116 return 0; 117 }
转载于:https://www.cnblogs.com/qldabiaoge/p/11403722.html