后缀自动机

没弄明白,做了几个题,也不懂,以后填坑
P3809 【模板】后缀排序

#include<bits/stdc++.h>
#define N 1000010
using namespace std;
int x[N],y[N],sa[N],h[N],rk[N],c[10*N],a[N];
char s[N];
int m,n;
void calcsa(int n,int m){
    int p=0,f=0;
    for(int i=1;i<=m;i++)c[i]=0;
    for(int i=1;i<=n;i++)c[x[i]=a[i]]++;
    for(int i=1;i<=m;i++)c[i]+=c[i-1];
    for(int i=n;i;i--)sa[c[x[i]]--]=i;
    for(int i=1;i<=n&&p<=n;i<<=1){
        p=0;
        for(int j=n-i+1;j<=n;j++)y[++p]=j;
        for(int j=1;j<=n;j++)if(sa[j]>i)y[++p]=sa[j]-i;
        for(int j=1;j<=m;j++)c[j]=0;
        for(int j=1;j<=n;j++)c[x[y[j]]]++;
        for(int j=1;j<=m;j++)c[j]+=c[j-1];
        for(int j=n;j;j--)sa[c[x[y[j]]]--]=y[j];
        swap(x,y);x[sa[1]]=1;p=2;
        for(int j=2;j<=n;j++)
        x[sa[j]]=y[sa[j]]==y[sa[j-1]]&&y[sa[j]+i]==y[sa[j-1]+i]?p-1:p++;
        m=p;
    }
}
int main(){
    scanf("%s",s+1);int len=strlen(s+1);
    for(int i=1;i<=len;i++)a[i]=s[i]-' ';
    calcsa(len,10000);
    for(int i=1;i<=len;i++)printf("%d ",sa[i]);
    return 0;
}
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

typedef long long ll;
const int maxn=1000010;

int n,last=1,cnt=1;
int a[maxn][26],mx[maxn],fa[maxn];
int T[maxn],Seq[maxn];
int f[maxn],w[maxn];
char s[maxn];
void insert(int c){
    int p=last,np=last=++cnt;
    mx[np]=mx[p]+1; f[np]=w[np]=1;
    while(!a[p][c] && p) a[p][c]=np,p=fa[p];
    if(!p) fa[np]=1;
    else{
        int q=a[p][c];
        if(mx[q]==mx[p]+1) fa[np]=q;
        else{
            int nq=++cnt;mx[nq]=mx[p]+1;
            memcpy(a[nq],a[q],sizeof(a[q]));
            fa[nq]=fa[q];
            fa[q]=fa[np]=nq;
            while(a[p][c]==q) a[p][c]=nq,p=fa[p];
        }
    }
}

ll solve(){ll ans=0;
    for(int i=1;i<=cnt;i++) T[mx[i]]++;
    for(int i=1;i<=n;i++) T[i]+=T[i-1];
    for(int i=1;i<=cnt;i++) Seq[T[mx[i]]--]=i;
    for(int i=cnt;i>=1;i--) f[fa[Seq[i]]]+=f[Seq[i]];
    for(int i=cnt;i>=1;i--){int x=Seq[i];
        ans+=(ll)f[x]*w[fa[x]]*mx[fa[x]];
        w[fa[x]]+=f[x];
    }
    return ans;
}
int main(){
    scanf("%s",s);n=strlen(s);
    for(int i=n-1;i>=0;i--) insert(s[i]-'a'); 
    ll ans=(ll)(1+n)*n*(n-1)/2;
    ans-=solve()*2;
    printf("%lld",ans);
    return 0;
}

P1368 工艺

#include<cstdio>
#include<iostream>
#include<map> 
#include<cstring>
using namespace std; 
const int M=1012000; 
int r[M],tmp[M],n,a[M];
struct SAM{
    map<int,int>ch[M];int f[M],size[M],dis[M],cnt,last;
    SAM(){cnt=last=1; }
    void insert(int x){
        int now=last,New=++cnt;last=cnt;size[New]=1;
        dis[New]=dis[now]+1;
        while(now&&!ch[now][x]) ch[now][x]=New,now=f[now];
        if(!now) f[New]=1;
        else{
            int p=ch[now][x];
            if(dis[p]==dis[now]+1) f[New]=p;
            else{
                int np=++cnt;ch[np]=ch[p];dis[np]=dis[now]+1;
                f[np]=f[p];f[New]=f[p]=np;
                while(now&&ch[now][x]==p) ch[now][x]=np,now=f[now];
            }
        }
    }

    void print(){int tmp=1;
        for(int i=1;i<=n;i++){
            printf("%d ",ch[tmp].begin()->first);
            tmp=ch[tmp].begin()->second;
        }

}
}T;
char s[M];
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]),a[n+i]=a[i];
    for(int i=1;i<=n;i++) T.insert(a[i]);
    for(int i=1;i<=n;i++) T.insert(a[i]);

    T.print();
} 

P3804 【模板】后缀自动机

// luogu-judger-enable-o2
#include<cstdio>
#include<iostream>
#include<map> 
#include<cstring>
using namespace std; 
const int M=2120000; 
int len,r[M],tmp[M];
struct SAM{
    int ch[M][30],f[M],size[M],dis[M],cnt,last;
    SAM(){memset(ch,0,sizeof ch);memset(dis,0,sizeof dis);memset(f,0,sizeof f);memset(size,0,sizeof size);cnt=last=1; }
    void insert(int x){
        int now=last,New=++cnt;last=cnt;size[New]=1;
        dis[New]=dis[now]+1;
        while(now&&!ch[now][x]) ch[now][x]=New,now=f[now];
        if(!now) f[New]=1;
        else{
            int p=ch[now][x];
            if(dis[p]==dis[now]+1) f[New]=p;
            else{
                int np=++cnt;memcpy(ch[np],ch[p],sizeof(ch[p]));dis[np]=dis[now]+1;
                f[np]=f[p];f[New]=f[p]=np;
                while(now&&ch[now][x]==p) ch[now][x]=np,now=f[now];
            }
        }
    }
    long long query(){long long ans=0;
        for(int i=1;i<=cnt;i++) r[dis[i]]++;
        for(int i=1;i<=len;i++) r[i]+=r[i-1];
        for(int i=1;i<=cnt;i++) tmp[r[dis[i]]--]=i;
        for(int i=cnt;i;i--){
            size[f[tmp[i]]]+=size[tmp[i]];
            if(size[tmp[i]]>1)ans=max(ans,1ll*dis[tmp[i]]*size[tmp[i]]);
        }
        return ans;
    }
    void print(){printf("%lld ",query());}
}T;
char s[M];
int main(){
    scanf("%s",s+1);
    len=strlen(s+1);
    for(int i=1;i<=len;i++) T.insert(s[i]-'a');
    T.print();
} 

P4070 [SDOI2016]生成魔咒

#include <iostream>
#include <cstdio>
#include <map>
#define ll long long
#define dist(x) (dis[x]-dis[fa[x]])
const int maxm=1e6+100;
std::map<int,int> ch[maxm*2];
int n,m,last=1,siz=1;
int fa[maxm],dis[maxm];
ll ans;
inline void insert(int x)
{
    int now=last,son=last=++siz; 
    dis[son]=dis[now]+1;
    while(now&&!ch[now][x]) ch[now][x]=son,now=fa[now];  
    if(!now) fa[son]=1,ans+=dist(son);  
    else { int q=ch[now][x];  
        if(dis[now]+1==dis[q]) fa[son]=q,ans+=dist(son);  
        else  {  
            int nq=++siz;dis[nq]=dis[now]+1;ch[nq]=ch[q];  
            fa[nq]=fa[q];ans+=dist(nq)-dist(q);  
            fa[son]=fa[q]=nq;ans+=dist(son)+dist(q);  
            while(now&&ch[now][x]==q) ch[now][x]=nq,now=fa[now];  
        }  
    }  
}
int main(){
    int n;
    scanf("%d",&n);
    for(int i=1,x;i<=n;i++){
        scanf("%d",&x);insert(x);
        printf("%lld\n",ans);
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值