[NOI2016]优秀的拆分
题意
一串字符串的子串能够被拆分成不重叠的$AABB$($A, B$为该子串的子串)的方案数
题解
考虑对子串进行隔离处理,枚举隔离长度$l$
那么在此隔离长度下若存在子串满足$AABB$,那么它必定横跨两个隔离点,那么此时求出每相邻两个隔离点的最长公共前缀$x$和最长公共后缀$y$(跑两遍$SA$求),那么若$x + y >= l$,那么必定可以构成$AABB$的子串(画下图就知道了),那么再统计数量,找到满足该条件的起始位置和终止位置,用差分就好了
代码
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 #include <vector> 7 8 using namespace std; 9 10 typedef long long LL; 11 12 const int MAXN = 3e04 + 10; 13 14 int T; 15 16 int N; 17 18 struct Suffix_Array { 19 char Str[MAXN]; 20 int M = 122; 21 int SA[MAXN]= {0}; 22 int Fir[MAXN]= {0}, Srk[MAXN]= {0}; 23 int buck[MAXN]= {0}; 24 void SA_Requirement () { 25 M = 122; 26 for (int i = 1; i <= M; i ++) 27 buck[i] = 0; 28 for (int i = 1; i <= N; i ++) 29 buck[Fir[i] = Str[i]] ++; 30 for (int i = 2; i <= M; i ++) 31 buck[i] += buck[i - 1]; 32 for (int i = N; i >= 1; i --) 33 SA[buck[Fir[i]] --] = i; 34 for (int k = 1; k <= N; k <<= 1) { 35 int p = 0; 36 for (int i = N - k + 1; i <= N; i ++) 37 Srk[++ p] = i; 38 for (int i = 1; i <= N; i ++) 39 if (SA[i] > k) 40 Srk[++ p] = SA[i] - k; 41 for (int i = 1; i <= M; i ++) 42 buck[i] = 0; 43 for (int i = 1; i <= N; i ++) 44 buck[Fir[i]] ++; 45 for (int i = 2; i <= M; i ++) 46 buck[i] += buck[i - 1]; 47 for (int i = N; i >= 1; i --) 48 SA[buck[Fir[Srk[i]]] --] = Srk[i], Srk[i] = 0; 49 swap (Fir, Srk); 50 Fir[SA[1]] = 1, p = 1; 51 for (int i = 2; i <= N; i ++) 52 Fir[SA[i]] = (Srk[SA[i]] == Srk[SA[i - 1]] && Srk[SA[i] + k] == Srk[SA[i - 1] + k]) ? p : ++ p; 53 if (p == N) 54 break; 55 M = p; 56 } 57 } 58 int Rank[MAXN]= {0}; 59 int Height[MAXN]= {0}; 60 void Height_Array () { 61 for (int i = 1; i <= N; i ++) 62 Rank[SA[i]] = i; 63 int k = 0; 64 for (int i = 1; i <= N; i ++) { 65 if (k) 66 k --; 67 int j = SA[Rank[i] - 1]; 68 while (j + k <= N && i + k <= N && Str[j + k] == Str[i + k]) 69 k ++; 70 Height[Rank[i]] = k; 71 } 72 } 73 74 int ST[MAXN][20]; 75 void RMQ () { 76 for (int i = 1; i <= N; i ++) 77 ST[i][0] = Height[i]; 78 for (int j = 1; j <= 18; j ++) 79 for (int i = 1; i + (1 << j) - 1 <= N; i ++) 80 ST[i][j] = min (ST[i][j - 1], ST[i + (1 << (j - 1))][j - 1]); 81 } 82 int Query (int l, int r) { 83 l ++; 84 int k = log2 (r - l + 1); 85 return min (ST[l][k], ST[r - (1 << k) + 1][k]); 86 } 87 int LCP (int x, int y) { 88 if (Rank[x] > Rank[y]) 89 swap (x, y); 90 return Query (Rank[x], Rank[y]); 91 } 92 void init () { 93 memset (SA, 0, sizeof (SA)); 94 memset (Height, 0, sizeof (Height)); 95 memset (Rank, 0, sizeof (Rank)); 96 memset (Fir, 0, sizeof (Fir)); 97 memset (Srk, 0, sizeof (Srk)); 98 } 99 } For, Rev; 100 101 int endwith[MAXN]= {0}, startwith[MAXN]= {0}; 102 103 int main () { 104 scanf ("%d", & T); 105 for (int Case = 1; Case <= T; Case ++) { 106 memset (endwith, 0, sizeof (endwith)); 107 memset (startwith, 0, sizeof (startwith)); 108 For.init (), Rev.init (); 109 scanf ("%s", For.Str + 1); 110 N = strlen (For.Str + 1); 111 for (int i = 1; i <= N; i ++) 112 Rev.Str[i] = For.Str[N - i + 1]; 113 For.SA_Requirement (), For.Height_Array (), For.RMQ (); 114 Rev.SA_Requirement (), Rev.Height_Array (), Rev.RMQ (); 115 LL ans = 0; 116 for (int l = 1; l <= (N >> 1); l ++) 117 for (int i = l, j = (l << 1); j <= N; i += l, j += l) { 118 int lcpfor = min (For.LCP (i, j), l); 119 int lcprev = min (Rev.LCP (N - j + 1, N - i + 1), l); 120 if (lcpfor + lcprev - 1 >= l) { 121 endwith[j + l - lcprev] ++; 122 endwith[j + lcpfor] --; 123 startwith[i - lcprev + 1] ++; 124 startwith[i - (l - lcpfor - 1)] --; 125 } 126 } 127 for (int i = 1; i <= N; i ++) { 128 endwith[i] += endwith[i - 1]; 129 startwith[i] += startwith[i - 1]; 130 } 131 for (int i = 1; i <= N; i ++) 132 ans += (LL) endwith[i] * startwith[i + 1]; 133 printf ("%lld\n", ans); 134 } 135 136 return 0; 137 } 138 139 /* 140 4 141 aabbbb 142 cccccc 143 aabaabaabaa 144 bbaabaababaaba 145 */ 146 147 /* 148 1 149 aabbbb 150 */ 151 152 /* 153 10 154 zzzzzzzzzzzzzzzzzzzzzzzzzzz 155 icicicicicicicicicicic 156 saasaasaasaasaasaasaa 157 znunznunznunznunznun 158 ttfhhttfhhttfhhttfhhttfhh 159 fqxqblfqxqblfqxqblfqxqblfqxqbl 160 xxpruxxpruxxpruxxpru 161 mpheqsmpheqsmpheqsmpheqs 162 ptvbemqptvbemqptvbemqptvbemq 163 nxykqknxykqknxykqknxykqk 164 */ 165 166 /* 167 1 168 mpheqsmpheqsmpheqsmpheqs 169 */