[Good] NOI2016 split (suffix array)

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:

  1. Appear in different locations of the same substring, we considered different sub-strings, they are excellent split will be credited to the answer.

  2. In one split, the allowed A = B . E.g.  cccc  presence of a resolving A = B = C .

  3. 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

Input # 1
  4
aabbbb 
cccccc 
aabaabaabaa 
bbaabaababaaba
Output # 1
  3
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;
}
View Code

 


 

I had the water commemorating the second black-title

 

 

 

 

 

 

 

 

  

Guess you like

Origin www.cnblogs.com/rentu/p/11426187.html