1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
| #pragma GCC diagnostic ignored "-Wchar-subscripts" #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 30005;
int n, lo2[maxn]; ll bg[maxn], ed[maxn], S[maxn], T[maxn]; char str[maxn];
struct SuffixArray { char s[maxn]; int sa[maxn], bkt1[maxn], bkt2[maxn], rk[maxn], ht[maxn]; int fir[maxn], sec[maxn], tmp[maxn]; int rmq[maxn][16]; void init() { memset(sa, 0, sizeof sa); memset(rk, 0, sizeof rk); memset(ht, 0, sizeof ht); memset(bkt1, 0, sizeof bkt1); memset(bkt2, 0, sizeof bkt2); memset(rmq, 0, sizeof rmq); memset(fir, 0, sizeof fir); memset(sec, 0, sizeof sec); memset(s, 0, sizeof s); memset(tmp, 0, sizeof tmp); } void build() { for (int i = 1; i <= n; ++i) bkt1[s[i]]++; for (int i = 1; i < 128; ++i) bkt1[i] += bkt1[i - 1]; for (int i = n; i; --i) sa[bkt1[s[i]]--] = i; rk[sa[1]] = 1; for (int i = 2; i <= n; ++i) rk[sa[i]] = rk[sa[i - 1]] + (s[sa[i]] != s[sa[i - 1]]); for (int len = 1; rk[sa[n]] < n; len <<= 1) { memset(bkt1, 0, sizeof bkt1); memset(bkt2, 0, sizeof bkt2); for (int i = 1; i <= n; ++i) { fir[i] = rk[i]; bkt1[fir[i]]++; sec[i] = (i + len <= n ? rk[i + len] : 0); bkt2[sec[i]]++; } for (int i = 1; i <= n; ++i) bkt1[i] += bkt1[i - 1], bkt2[i] += bkt2[i - 1]; for (int i = n; i; --i) tmp[bkt2[sec[i]]--] = i; for (int i = n; i; --i) sa[bkt1[fir[tmp[i]]]--] = tmp[i]; rk[sa[1]] = 1; for (int i = 2; i <= n; ++i) rk[sa[i]] = rk[sa[i - 1]] + (fir[sa[i]] != fir[sa[i - 1]] || sec[sa[i]] != sec[sa[i - 1]]); }
for (int i = 1, j = 0; i <= n; ++i) { j = j ? j - 1 : 0; while (s[i + j] == s[sa[rk[i] - 1] + j]) ++j; ht[rk[i]] = j; }
for (int i = 1; i <= n; ++i) rmq[i][0] = ht[i]; for (int i = 1; (1 << i) <= n; ++i) for (int j = 1; j + (1 << i) - 1 <= n; ++j) { rmq[j][i] = min(rmq[j][i - 1], rmq[j + (1 << (i - 1))][i - 1]); } } inline int query(int l, int r) { int len = r - l + 1; return min(rmq[l][lo2[len]], rmq[r - (1 << lo2[len]) + 1][lo2[len]]); } }SA, SA2;
int main() { int Ts; scanf("%d", &Ts); lo2[1] = 0; for (int i = 2; i <= 30000; ++i) lo2[i] = lo2[i >> 1] + 1; while (Ts--) { scanf("%s", str + 1); n = strlen(str + 1); SA.init(); SA2.init(); for (int i = 1; i <= n; ++i) SA.s[i] = str[i], SA2.s[i] = str[n - i + 1]; SA.build(); SA2.build(); memset(bg, 0, sizeof bg); memset(ed, 0, sizeof ed); memset(S, 0, sizeof S); memset(T, 0, sizeof T); for (int i = 1; i <= n; ++i) { for (int p = i + 1; p <= n; p += i) { int lst = SA.rk[p - i + 1], ths = SA.rk[p + 1]; if (lst > ths) swap(lst, ths); int rlst = SA2.rk[n - (p - i) + 1], rths = SA2.rk[n - p + 1]; if (rlst > rths) swap(rlst, rths); int lcp = SA.query(lst + 1, ths); int rlcp = SA2.query(rlst + 1, rths); if (lcp + rlcp < i || !rlcp) continue; int l = max(p - 2 * i + 1, p - i - rlcp + 1); int r = min(p + i - 1, p + lcp); S[l]++; S[r - 2 * i + 2]--; T[l + 2 * i - 1]++; T[r + 1]--; } } for (int i = 1; i <= n; ++i) bg[i] = bg[i - 1] + S[i], ed[i] = ed[i - 1] + T[i]; ll ans = 0; for (int i = 2; i <= n; ++i) ans += bg[i] * ed[i - 1]; printf("%lld\n", ans); } return 0; }
|