根据常用套路,用一个奇怪的字符把$A$,$B$连接起来,然后二分答案,然后按mid分组。
分完组考虑如何统计每一组的贡献。
对于每一组内每一对$(A_i , B_j)$考虑拆成两部分:
- $rank(A_i) < rank(B_j)$
- $rank(A_i) > rank(B_j)$
然后就可以从小到大枚举每一个串,然后考虑前面的$A_i$或$B_j$的贡献。
显然这个贡献从当前串的前一个串往前走单调不增,然后就拿个单调栈维护就完了。
Code
1 /** 2 * poj 3 * Problem#3415 4 * Accepted 5 * Time: 1110ms 6 * Memory: 10232k 7 */ 8 #include <iostream> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cstdio> 12 #ifndef WIN32 13 #define Auto "%lld" 14 #else 15 #define Auto "%I64d" 16 #endif 17 using namespace std; 18 typedef bool boolean; 19 #define ll long long 20 21 #define pii pair<int, int> 22 #define fi first 23 #define sc second 24 25 const int N = 2e5 + 5; 26 27 typedef class Pair3 { 28 public: 29 int x, y, id; 30 31 Pair3() { } 32 Pair3(int x, int y, int id):x(x), y(y), id(id) { } 33 }Pair3; 34 35 typedef class SuffixArray { 36 protected: 37 Pair3 T1[N], T2[N]; 38 int cnt[N]; 39 40 public: 41 int n; 42 char *str; 43 int sa[N], rk[N], hei[N]; 44 45 void set(int n, char* str) { 46 this->n = n; 47 this->str = str; 48 memset(sa, 0, sizeof(sa)); 49 memset(rk, 0, sizeof(rk)); 50 memset(hei, 0, sizeof(hei)); 51 } 52 53 void radix_sort(Pair3* x, Pair3* y) { 54 int m = max(n, 256); 55 memset(cnt, 0, sizeof(int) * m); 56 for (int i = 0; i < n; i++) 57 cnt[x[i].y]++; 58 for (int i = 1; i < m; i++) 59 cnt[i] += cnt[i - 1]; 60 for (int i = 0; i < n; i++) 61 y[--cnt[x[i].y]] = x[i]; 62 63 memset(cnt, 0, sizeof(int) * m); 64 for (int i = 0; i < n; i++) 65 cnt[y[i].x]++; 66 for (int i = 1; i < m; i++) 67 cnt[i] += cnt[i - 1]; 68 for (int i = n - 1; ~i; i--) 69 x[--cnt[y[i].x]] = y[i]; 70 } 71 72 void build() { 73 for (int i = 0; i < n; i++) 74 rk[i] = str[i]; 75 for (int k = 1; k < n; k <<= 1) { 76 for (int i = 0; i + k < n; i++) 77 T1[i] = Pair3(rk[i], rk[i + k], i); 78 for (int i = n - k; i < n; i++) 79 T1[i] = Pair3(rk[i], 0, i); 80 radix_sort(T1, T2); 81 int diff = 0; 82 rk[T1[0].id] = 0; 83 for (int i = 1; i < n; i++) 84 rk[T1[i].id] = (T1[i].x == T1[i - 1].x && T1[i].y == T1[i - 1].y) ? (diff) : (++diff); 85 if (diff == n - 1) 86 break; 87 } 88 for (int i = 0; i < n; i++) 89 sa[rk[i]] = i; 90 } 91 92 void get_height() { 93 for (int i = 0, j, k = 0; i < n; i++, (k) ? (k--) : (0)) { 94 if (rk[i]) { 95 j = sa[rk[i] - 1]; 96 while (i + k < n && j + k < n && str[i + k] == str[j + k]) k++; 97 hei[rk[i]] = k; 98 } 99 } 100 } 101 102 const int& operator [] (int p) { 103 return sa[p]; 104 } 105 106 const int& operator () (int p) { 107 return hei[p]; 108 } 109 }SuffixArray; 110 111 int K; 112 int n, m; 113 char S[N]; 114 SuffixArray sa; 115 116 inline boolean init() { 117 scanf("%d", &K); 118 if (!(K--)) 119 return false; 120 scanf("%s", S); 121 n = strlen(S); 122 S[n] = '#'; 123 scanf("%s", S + n + 1); 124 m = strlen(S + n + 1); 125 n += m + 1; 126 sa.set(n, S); 127 return true; 128 } 129 130 ll res = 0, sum; 131 int tp = 0; 132 pii st[N]; 133 inline void solve(int L, int R) { // Calculate the s_i (i in [L, R)) 134 if (R - L < 2) 135 return ; 136 tp = sum = 0; 137 for (int i = L, sg; i < R - 1; i++) { 138 sg = (sa[i] < n - m - 1); 139 if (!sg) 140 res += sum; 141 while (tp && st[tp].fi >= sa(i + 1)) 142 sg += st[tp].sc, sum -= st[tp].sc * 1ll * (st[tp].fi - K), tp--; 143 sum += (sa(i + 1) - K) * 1ll * sg; 144 st[++tp] = pii(sa(i + 1), sg); 145 } 146 if (!(sa[R - 1] < n - m - 1)) 147 res += sum; 148 149 tp = sum = 0; 150 for (int i = L, sg; i < R - 1; i++) { 151 sg = !(sa[i] < n - m - 1); 152 if (!sg) 153 res += sum; 154 while (tp && st[tp].fi >= sa(i + 1)) 155 sg += st[tp].sc, sum -= st[tp].sc * 1ll * (st[tp].fi - K), tp--; 156 sum += (sa(i + 1) - K) * 1ll * sg; 157 st[++tp] = pii(sa(i + 1), sg); 158 } 159 if (sa[R - 1] < n - m - 1) 160 res += sum; 161 } 162 163 inline void solve() { 164 res = 0; 165 sa.build(); 166 sa.get_height(); 167 168 int lst = 0; 169 for (int i = 0; i < n; i++) 170 if (sa(i) < K + 1) 171 solve(lst, i), lst = i; 172 solve(lst, n); 173 printf(Auto" ", res); 174 } 175 176 int main() { 177 while (init()) 178 solve(); 179 return 0; 180 }