Title Description
If a string can be broken into the AABB A A B Form B, wherein A and B are any non-empty string, then the string we call this resolution is excellent.
For example, for strings aabaabaa , supposing A AAB = , B = A , we have found this string split into AABB one way.
A string may not be good resolution, there may be more than one outstanding split. For example we let A = A , B = BAA , can also be used AABB shows the character string; however, the string abaabaa no excellent resolution.
Will now be given of a length n of the string S , we need to find, in all the way it resolved in all sub-strings, the total number of outstanding split. Substring herein refers to a contiguous stretch of string.
Note the following points:
-
Appear in different locations of the same substring, we considered different sub-strings, they are excellent split will be credited to the answer.
-
In one split, the allowed A = B . E.g. cccc presence of a resolving A = B = C .
-
The string itself is one of its string.
Input Format
Each input file contains multiple sets of data.
Only a first line of input integer T, represents a group of data. Ensure 1≤T≤10 .
Next T lines, each line comprising a string consisting only English lowercase letters S , such as the title of the meaning.
Output Format
Output T lines, each comprising an integer representing the string S all substrings of all split, is the total number of outstanding split.
Sample input and output
aabbbb cccccc aabaabaabaa bbaabaababaaba
5 4 7
[Title] effect
Given a string inside look from a total number of strings meet AABB form, the number of output
【Analysis of Algorithms】
Consider this splice case, AABB
So we just need to find all of the AA / BB, then take the left and right to get the final answer
Then the question becomes how to seek conversion of AA and BB
We can find use suffix array LCP taken within the time complexity nlogn
At the same time we flip the string, then we can request to LCS
If these two strings coincide, this can occur will be described in the form of repeated AA
definition:
f [i] for the i meet the conditions of the beginning of the string type AA
G [i] to end with the i-type string qualified AA
Then we just need to multiply those add up to a
note:
The last can not overlap, the last position (n) does not meet the requirements
[Code]
#include<cstdio> #include<cstring> #include<string> #include<iostream> #include<algorithm> using namespace std; const int MAXN = 30000+ 5; int lg[MAXN], f[MAXN], g[MAXN]; struct suff_string { int n,m; int x[MAXN] = { 0 }, y[MAXN] = { 0 }, c[MAXN] = { 0 }; int SA[MAXN], rak[MAXN], height[MAXN]; int st[17][MAXN]; void build_SA(char *s) { n = strlen(s + 1); m = 128; for (int i = 1; i <= 30000; i++) x[i] = y[i] = c[i] = 0; for (int i = 1; i <= n; i++) SA[i] = rak[i] = height[i] = 0; for (int i = 1; I <= n-; I ++ ) ++ C [X [I] = S [I]]; // count the number of characters each, the same together for ( int I = 2 ; I <= m; I ++ ) C [I] + C = [I - . 1 ]; // find a prefix, and for ( int I = n-; I> = . 1 ; i-- ) SA [C [X [I]] -] = I; // from the back, so that we can determine the beginning of the sequence for ( int K = . 1 ; K <= n-; = K << . 1 ) { int NUM = 0; For ( int I = n-- K + . 1 ; I <= n-; I ++) Y [NUM ++] = I; // the last few characters into it for ( int I = . 1 ; I <= n-; I ++ ) // order traversal IF (SA [I]> K) // If the length is greater than K Y [NUM ++] = SA [I] - K; // put into it first for ( int I = . 1 ; I <= m; I ++ ) C [I] = 0 ; for (int i = 1; i <= n; i++) c[x[i]]++; //x[i]是第一关键字 for (int i = 2; i <= m; i++) c[i] += c[i - 1]; //求前缀和 for (int i = n; i >= 1; i--) SA[c[x[y[i]]]--] = y[i], y[i] = 0; swap(x, y); x[SA[1]] = 1; num = 1; for (int i = 2; i <= n; i++) x[SA[i]] = (y[SA[i]] == y[SA[i - 1]] && y[SA[i] + k] == y[SA[i - 1] + k]) ? num : ++num; if (num == n) break; m = num; } for (int i = 1; i <= n; i++) rak[SA[i]] = i; return; } void get_height(char *s) { int k = 0; for (int i = 1; i <= n; i++) { if (k) k--; int j = SA[rak[i] - 1]; while (i+k<=n && j+k<=n &&s[i + k] == s[j + k]) k++; height[rak[i]] = k; } } void build_ST() { memset(st, 0, sizeof(st)); for (int i = 1; i <= n; i++) st[0][i] = height[i]; //printf("1\n"); for (int i = 1; i <= 16; i++) for (int j = 1; j <= n; j++) st[i][j] = min(st[i - 1][j], st[i - 1][j + (1 << (i - 1))]); //printf("2\n"); } int query(int l, int r) { l = rak[l],r = rak[r]; if (l > r) swap(l, r); l++; int t = lg[r + 1 - l]; return min(st[t][l], st[t][r - (1 << t) + 1]); } }A,B; char s[MAXN]; void solve() { //printf("%s\n", s+1); //printf("**\n"); scanf("%s", s + 1); A.build_SA(s); A.get_height(s); A.build_ST(); int N = A.n; reverse(s + 1, s + 1 + N); //printf("%s\n", s + 1); B.build_SA(s); B.get_height(s); B.build_ST(); //printf("%d %d \n",A.n,B.n); for (int i = 1; i <=N; i++) f[i] = 0, g[i] = 0; for (int len = 1; len <= N / 2; len++) { for (int i = len, j = i + len; j <= N; i += len, j += len) { // printf("**\n"); int lcp = min(A.query(i, j), len), lcs = min(B.query(N - i + 2, N - j + 2), len - 1); // printf("**\n"); int t = lcp + lcs - len + 1; if (lcp + lcs >= len) { g[i - lcs]++, g[i - lcs + t]--; f[j + lcp - t]++, f[j + lcp]--; } } } //printf("**\n"); for (int i = 1; i <= N; i++) f[i] += f[i - 1], g[i] += g[i - 1]; long long ans = 0; for (int i = 1; i <N; i++) ans += 1ll * f[i] * g[i + 1]; printf("%lld\n", ans); } int main() { int T; for (int i = 2; i <= 30000; i++) lg[i] = lg[i >> 1] + 1; scanf("%d", &T); while (T--) { solve(); } return 0; }
I had the water commemorating the second black-title