UOJ # 219 BZOJ 4650 luogu P1117 [NOI2016] excellent resolution (suffix array, ST table)

Even NOI Day1T1 will not do. . . Read the solution to a problem can not write to Claris also copied code. .

Topic links: (luogu) https://www.luogu.org/problemnew/show/P1117

(bzoj)https://www.lydsy.com/JudgeOnline/problem.php?id=4650

(uoj) http://uoj.ac/problem/219

answer:

\ (f [i] \) represented by \ (I \) end \ (AA \) the number of sub-string, \ (G [I] \) represented by \ (I \) starting \ (AA \) the number of sub-type string

How demand \ (f, G \) ?

Break the mindset, who said a request it must be a

Sublength to seek

Enumeration length \ (L \) , handles all of the length \ (2L \) a \ (AA \) type of the substring \ (F \) and \ (G \) contributed

If every \ (L \) to a discharge point timer length, Bah, key

Then any \ (AA \) type substring will go through two adjacent key points

First, we must meet the characters on these two key positions as

On this basis, the maximum number is determined to move forward in the future the same

This would translate into LCP and LCS problem, and the two adjacent key points \ (f, g \) the impact of the array is the interval +1 prefix and solve differential

Then push a push on the line, do not push the wrong note + 1-1

The time complexity is the harmonic series, \ (O (n-\ log n-) \)

Code

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define llong long long
using namespace std;

const int N = 1<<15;
const int LGN = 15;
const int S = 26;
int log2[N+3];
struct SparseTable
{
    int n;
    int str[N+3];
    int rk[N+3];
    int tmp[N+3];
    int height[N+3];
    int h[N+3];
    int sa[N+3];
    int wb[N+3];
    int mini[N+3][LGN+3];
    void get_sa()
    {
        int *x = rk,*y = tmp;
        for(int i=0; i<=S; i++) wb[i] = 0;
        for(int i=1; i<=n; i++) wb[x[i]=str[i]]++;
        for(int i=1; i<=S; i++) wb[i] += wb[i-1];
        for(int i=n; i>=1; i--) sa[wb[x[i]]--] = i;
        int s = S,p = 0;
        for(int j=1; p<n; j<<=1)
        {
            p = 0;
            for(int i=n-j+1; i<=n; i++) y[++p] = i;
            for(int i=1; i<=n; i++) if(sa[i]>j) y[++p] = sa[i]-j;
            for(int i=1; i<=s; i++) wb[i] = 0;
            for(int i=1; i<=n; i++) wb[x[y[i]]]++;
            for(int i=1; i<=s; i++) wb[i] += wb[i-1];
            for(int i=n; i>=1; i--) sa[wb[x[y[i]]]--] = y[i];
            swap(x,y);
            p = 1; x[sa[1]] = 1;
            for(int i=2; i<=n; i++) x[sa[i]] = (y[sa[i]]==y[sa[i-1]] && y[sa[i]+j]==y[sa[i-1]+j]) ? p : ++p;
            s = p;
        }
        for(int i=1; i<=n; i++) rk[sa[i]] = i;
        for(int i=1; i<=n; i++)
        {
            h[i] = h[i-1]==0 ? 0 : h[i-1]-1;
            while(i+h[i]<=n && sa[rk[i-1]]+h[i]<=n && str[i+h[i]]==str[sa[rk[i]-1]+h[i]])
            {
                h[i]++;
            }
        }
        for(int i=1; i<=n; i++) height[i] = h[sa[i]];
        for(int i=1; i<=n; i++) mini[i][0] = height[i];
        for(int j=1; j<=LGN; j++)
        {
            for(int i=1; i+(1<<j)-1<=n; i++)
            {
                mini[i][j] = min(mini[i][j-1],mini[i+(1<<j-1)][j-1]);
            }
        }
    }
    int querymin(int lb,int rb)
    {
        int g = log2[rb-lb+1];
        return min(mini[lb][g],mini[rb-(1<<g)+1][g]);
    }
    int LCP(int x,int y)
    {
        if(x==y) return n-x+1;
        if(rk[x]>rk[y]) swap(x,y);
        return querymin(rk[x]+1,rk[y]);
    }
    void clear()
    {
        for(int i=1; i<=n; i++) str[i] = rk[i] = tmp[i] = height[i] = h[i] = sa[i] = wb[i] = 0;
        for(int i=1; i<=n; i++)
        {
            for(int j=0; j<=LGN; j++)
            {
                mini[i][j] = 0;
            }
        }
    }
} s1,s2;
llong f[N+3];
llong g[N+3];
char a[N+3];
int n;

int LCP(int x,int y) {return s1.LCP(x,y);}
int LCS(int x,int y) {return s2.LCP(n+1-x,n+1-y);}

void preprocess()
{
    log2[1] = 0; for(int i=2; i<=N; i++) log2[i] = log2[i>>1]+1;
}

void clear()
{
    s1.clear(); s2.clear();
    for(int i=0; i<=n+1; i++) a[i] = 0,f[i] = g[i] = 0ll;
}

int main()
{
    preprocess();
    int T; scanf("%d",&T);
    while(T--)
    {
        scanf("%s",a+1); n = strlen(a+1); for(int i=1; i<=n; i++) a[i]-=96;
        for(int i=1; i<=n; i++) s1.str[i] = a[i]; s1.n = n;
        s1.get_sa();
        for(int i=1; i<=n; i++) s2.str[i] = a[n+1-i]; s2.n = n;
        s2.get_sa();
        for(int i=1; i+i<=n; i++)
        {
            for(int j=i+i; j<=n; j+=i)
            {
                if(a[j]==a[j-i])
                {
                    int lb = j-LCS(j,j-i)+1,rb = j+LCP(j,j-i)-1;
                    lb = max(lb+i-1,j); rb = min(rb,j+i-1);
                    if(lb<=rb)
                    {
                        f[lb]++; f[rb+1]--;
                        g[lb-i-i+1]++; g[rb+1-i-i+1]--;
                    }
                }
            }
        }
        for(int i=1; i<=n; i++) f[i] += f[i-1],g[i] += g[i-1];
        llong ans = 0ll;
        for(int i=1; i<n; i++)
        {
            llong tmp = f[i]*g[i+1];
            ans += tmp;
        }
        printf("%lld\n",ans);
        clear();
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/suncongbo/p/11032784.html