BZOJ3238 SA // SAM

Topic Link

Meaning of the questions: LCP seeking pairwise suffix and

A practice:

It is easy to think of suffix array, Height array represents the suffix of two adjacent LCP ranking

It will be appreciated that any two suffixes LCP Height is the minimum between them, so long as each point is calculated as a minimum cover Height leftmost and rightmost point, r [i] - i + 1- - i - l [i] + 1 suffix number of the current section is formed as a minimum Height

This is a classic problem // DP stack monotonic, linear Both methods seek out, should be particularly noted that both methods should be noted that the same calculation is repeated to bring back Height, height e.g. 1,1,1 directly values ​​are then calculated for each tube to [1,3], so as to close a left-right-left opening where the opening or closing of the right, i.e., [1,3], [2,3], [3,3]

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <bitset>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)  
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))  
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x)  
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x)  
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long  
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second 
typedef vector<int> VI;
int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();}
while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;}
const double PI = acos(-1.0);
const double eps = 1e-9;
const int maxn = 5e5 + 10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7; 
int N,M,K;
char str[maxn];
int sa[maxn],rak[maxn],tex[maxn],tp[maxn],Height[maxn];
void GetHeight(){
    int j,k = 0;
    for(int i = 1; i <= N ; i ++){
        if(k) k--;
        int j = sa[rak[i] - 1];
        while(str[i + k] == str[j + k]) k++;
        Height[rak[i]] = k;
    }
} 
void Qsort(){
    for(int i = 0; i <= M; i ++) tex[i] = 0;
    for(int i = 1; i <= N; i ++) tex[rak[i]]++;
    for(int i = 1; i <= M; i ++) tex[i] += tex[i - 1];
    for(int i = N; i >= 1; i --) sa[tex[rak[tp[i]]]--] = tp[i];
}
void SA(){
    for(int i = 1; i <= N ; i ++) rak[i] = str[i] - 'a' + 1,tp[i] = i;
    Qsort();
    for(int w = 1,p = 0; p < N; w <<= 1,M = p){
        p = 0;
        for(int i = 1; i <= w; i ++) tp[++p] = N - w + i;
        for(int i = 1; i <= N; i ++) if(sa[i] > w) tp[++p] = sa[i] - w;
        Qsort();
        swap(tp,rak);
        rak[sa[1]] = p = 1;
        for(int i = 2; i <= N; i ++){
            rak[sa[i]] = (tp[sa[i - 1]] == tp[sa[i]] && tp[sa[i - 1] + w] == tp[sa[i] + w])?p:++p;
        }
    }
}
int Stack[maxn],top;
int l[maxn],r[maxn];
int main(){
    scanf("%s",str + 1); N = strlen(str + 1);
    M = 122;
    SA(); GetHeight();
    for(int i = 1; i <= N ; i ++){
        while(top && Height[Stack[top]] > Height[i]) top--;
        l[i] = Stack[top] + 1;
        Stack[++top] = i;
    }
    top = 0; Stack[0] = N + 1;
    for(int i = N; i >= 1; i --){
        while(top && Height[Stack[top]] >= Height[i]) top--;
        r[i] = Stack[top] - 1;
        Stack[++top] = i;
    }
    LL sum = 1ll * (N - 1) * (1 + N) * N / 2;
    for(int i = 1; i <= N; i ++){
        //cout << l[i] << " " << r[i] << endl;
        sum -= 1ll * 2 * (r[i] - i + 1) * (i - l[i] + 1) * Height[i];
    }
    Prl(sum);
    return 0;
}
SADDLE

 

Practice two:

SAM is an important nature parent tree, the longest common suffix two nodes is the longest string representation they LCA

Therefore, we will reverse the string, it becomes len [LCA] between each two representatives seeking the N prefix key points and, in fact right subtree array representation is the number of critical points,

So you can key point for each point number is num [u] * (num [u] - 1) - Σnum [v] - (num [v] - 1) (v u for the son)

Can log O (n) calculated, minus the last time statistics on the number of * len [i] can be.

After subtracting the contribution as a minus, to understand a little bit abstract, is included in all contributions can also use the num [i] * (num [i] - - 1) * (len [fa [i] len [i]) LCA father and above the point of contribution

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <bitset>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)  
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))  
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x)  
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x)  
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long  
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second 
typedef vector<int> VI;
int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();}
while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;}
const double PI = acos(-1.0);
const double eps = 1e-9;
const int maxn = 5e5 + 10;
const int maxc = 26;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7; 
int N,M,K;
int len[maxn << 1],fa[maxn << 1],son[maxn << 1][maxc];
LL num[maxn << 1];
int size,last;
LL sum;
void Init(){
    size = last = 1;
}
void insert(char c){
    int s = c - 'a';
    int p = last,np = ++size;last = np; 
    //cout << np << endl;
    len[np] = len[p] + 1; num[np] = 1; 
    for(;p && !son[p][s]; p = fa[p]) son[p][s] = np;
    if(!p) fa[np] = 1;
    else{
        int q = son[p][s];
        if(len[p] + 1 == len[q]) fa[np] = q;
        else{
            int nq = ++size; len[nq] = len[p] + 1;
            memcpy(son[nq],son[q],sizeof(son[q]));
            fa[nq] = fa[q]; fa[q] = fa[np] = nq; 
            for(;son[p][s] == q && p;p = fa[p]) son[p][s] = nq;
        }
    }
}
int A[maxn << 1],tmp[maxn << 1];
void Qsort(){
    for(int i = 1; i <= size; i ++) tmp[len[i]]++;
    for(int i = 1; i <= size; i ++) tmp[i] += tmp[i - 1];
    for(int i = 1; i <= size; i ++) A[tmp[len[i]]--] = i;
}
char str[maxn];
LL dp[maxn << 1];
int main(){
    scanf("%s",str); N = strlen(str);
    reverse(str,str + N);
    sum = 1ll * (N - 1) * (N + 1) * N / 2; Init();
    for(int i = 0 ; i < N ; i ++) insert(str[i]);
    Qsort();
    for(int i = size; i >= 1; i --) num[fa[A[i]]] += num[A[i]];
    for(int i = 2; i <= size; i ++){
        sum -= (len[i] - len[fa[i]]) * num[i] * (num[i] - 1);
    }
//    for(int i = 2; i <= size; i ++) sum -= len[i] * dp[i];
    Prl(sum);
    return 0;
}
SAM

 

Guess you like

Origin www.cnblogs.com/Hugh-Locke/p/11511547.html