BZOJ4566 [Haoi2016]找相同字符

看一眼题,觉得和3473好像啊,然而3473我还没做呢……

造一个广义后缀自动机,siz开成二维把两个串的siz分开来算,每个节点对答案的贡献为(mx[x]-mx[fa[x]])*siz[0][x]*siz[1][x]

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
using namespace std;
#define MAXN 800010
#define MAXM 1010
#define ll long long
#define INF 1000000000
#define MOD 1000000007
#define eps 1e-8
int v[MAXN];
int p[MAXN];
struct sam{
    int fa[MAXN],mx[MAXN],siz[2][MAXN],son[MAXN][26];
    int rt,lst,tot;
    sam(){
        rt=lst=tot=1;
    }
    void ins(int x,int f){
        int np=++tot,p=lst;
        mx[np]=mx[p]+1;
        while(p&&!son[p][x]){
            son[p][x]=np;
            p=fa[p];
        }
        if(!p){
            fa[np]=rt;
        }else{
            int q=son[p][x];
            if(mx[q]==mx[p]+1){
                fa[np]=q;
            }else{
                int nq=++tot;
                mx[nq]=mx[p]+1;
                memcpy(son[nq],son[q],sizeof(son[q]));
                fa[nq]=fa[q];
                fa[np]=fa[q]=nq;
                while(p&&son[p][x]==q){
                    son[p][x]=nq;
                    p=fa[p];
                }
            }
        }
        lst=np;
    }
    void pre(){
        int i;
        memset(v,0,sizeof(v));
        for(i=1;i<=tot;i++){
            v[mx[i]]++;
        }
        for(i=1;i<=tot;i++){
            v[i]+=v[i-1];
        }
        for(i=tot;i;i--){
            p[v[mx[i]]--]=i;
        }
        for(i=tot;i;i--){
            siz[0][fa[p[i]]]+=siz[0][p[i]];
            siz[1][fa[p[i]]]+=siz[1][p[i]];
        }
    }
};
sam a;
char s1[MAXN],s2[MAXN];
int l1,l2;
bool visa[MAXN],visb[MAXN];
ll ans;
int main(){
    int i;
    scanf("%s%s",s1+1,s2+1);
    l1=strlen(s1+1);
    l2=strlen(s2+1);
    int p=a.rt;
    for(i=1;i<=l1;i++){
        a.ins(s1[i]-'a',0);
        p=a.son[p][s1[i]-'a'];
        a.siz[0][p]++;
    }
    a.lst=1;
    p=a.rt;
    for(i=1;i<=l2;i++){
        a.ins(s2[i]-'a',1);
        p=a.son[p][s2[i]-'a'];
        a.siz[1][p]++;
    }
    a.pre();
    for(i=1;i<=a.tot;i++){
        ans+=(ll)(a.mx[i]-a.mx[a.fa[i]])*a.siz[0][i]*a.siz[1][i];
    }
    printf("%lld\n",ans);
    return 0;
}
 
/*
 
*/</span>


你可能感兴趣的:(BZOJ4566 [Haoi2016]找相同字符)