學習筆記 字尾自動機SAM

2022-04-29 23:21:07 字數 4632 閱讀 1109

好抽象啊,早上看了兩個多小時才看懂,\(\%\%\%fading\) 早就懂了

講解就算了吧……可以去看看其他人的部落格

\(siz\) 為該串出現的次數,\(l\) 為子串長度,每次乘一下就好了

\(code\ below:\)

#include #define ll long long

using namespace std;

const int maxn=2000000+10;

int n,a[maxn],c[maxn],last,cnt,ch[maxn][26],fa[maxn],l[maxn],siz[maxn];

char s[maxn];ll ans;

void insert(int c)

} siz[q]=1;

}int main()

printf("%lld\n",ans);

return 0;

}

題意簡述:\([tjoi2015]\) 弦論找第 \(k\) 小子串 \(t=0\) 的弱化版

直接像權值線段樹找第 \(k\) 小就好了

\(code\ below:\)

#include using namespace std;

const int maxn=200000+10;

int n,q,a[maxn],c[maxn],last,cnt,ch[maxn][26],fa[maxn],l[maxn],siz[maxn];

char s[maxn];

void insert(int c) }}

int main()

scanf("%d",&q);

int k,p;

while(q--)

else k-=siz[ch[p][i]];

}} putchar('\n');

} return 0;

}

\(t=1\) 的時候就是像模板一樣記錄一下 \(siz\),拓撲一遍

\(code\ below:\)

#include using namespace std;

const int maxn=1000000+10;

int n,q,t,a[maxn],c[maxn],last,cnt,ch[maxn][26],fa[maxn],l[maxn],siz[maxn],sum[maxn];

char s[maxn];

void insert(int c)

}siz[q]=1;

}int main()

siz[1]=0;

for(int i=cnt;i>=1;i--)

if(k>sum[1])

while(k)

else k-=sum[ch[p][i]];}}

putchar('\n');

return 0;

}

題意:找兩個串的最長公共子串

類似 \(kmp\) 一樣匹配兩個串,失配的話一直向上跳

\(code\ below:\)

#include using namespace std;

const int maxn=500000+10;

int n,a[maxn],c[maxn],last,cnt,ch[maxn][26],fa[maxn],l[maxn],ans;

char s[maxn];

void insert(int c) }}

int main()

ans=max(ans,len);

} printf("%d\n",ans);

return 0;

}

題意:找多個串的最長公共子串

類似雙串 \(lcs\) 一樣,就是在匹配的時候記錄下來長度,先取個 \(min\),再在 \(min\) 中取個 \(max\)

\(code\ below:\)

#include using namespace std;

const int maxn=200000+10;

int n,a[maxn],c[maxn],last,cnt,ch[maxn][26],fa[maxn],l[maxn],max[maxn],min[maxn],ans;

char s[maxn];

void insert(int c) }}

int main()

} for(int i=cnt;i>=1;i--)

} for(int i=2;i<=cnt;i++) ans=max(ans,min[i]);

printf("%d\n",ans);

return 0;

}

題意:問多少條本質不同路徑(可以翻轉)

邊搜邊建。因為葉子結點只有 \(20\) 個,每次就以度數為 \(1\) 的點開始搜尋,建乙個廣義字尾自動機。

#include #define ll long long

using namespace std;

const int maxn=200000+10;

int n,m,a[maxn],in[maxn],ch[maxn*20][26],fa[maxn*20],l[maxn*20],cnt;

int head[maxn],to[maxn<<1],nxt[maxn<<1],tot;ll ans;

inline int read()

while(isdigit(ch))

return (f==1)?x:-x;

}inline void add(int x,int y)

int insert(int c,int p)

} return q;

}void dfs(int x,int f,int p)

}int main()

while(isdigit(ch))

return (f==1)?x:-x;

}void insert(int c) }}

void pushup(int now)

void update(int &now,int l,int r,int x)

int mid=(l+r)>>1;

if(x <= mid) update(l[now],l,mid,x);

else update(r[now],mid+1,r,x);

pushup(now);

}int merge(int x,int y,int l,int r)

int mid=(l+r)>>1,z=++tot;

l[z]=merge(l[x],l[y],l,mid);

r[z]=merge(r[x],r[y],mid+1,r);

pushup(z);

return z;

}int query(int now,int le,int ri,int l,int r)

int check(int len,int x,int l,int r)

int main()

for(int i=1;i<=cnt;i++) b[l[i]]++;

for(int i=1;i<=cnt;i++) b[i]+=b[i-1];

for(int i=1;i<=cnt;i++) a[b[l[i]]--]=i;

for(int i=cnt;i>=1;i--)

if(fa[a[i]]) t[fa[a[i]]]=merge(t[fa[a[i]]],t[a[i]],1,n);

for(int i=1;i<=cnt;i++) f[i][0]=fa[i];

for(int j=1;j<=20;j++)

for(int i=1;i<=cnt;i++) f[i][j]=f[f[i][j-1]][j-1];

int a,b,c,d,l,r,mid,ans;

while(m--)

printf("%d\n",ans);

} return 0;

}

題意:問兩個串的公共子串個數

如核心** \((l[i]-l[fa[i]])\times siz[i]\)

for(int i=2;i<=cnt;i++) sum[a[i]]=sum[fa[a[i]]]+(ll)(l[a[i]]-l[fa[a[i]]])*siz[a[i]];

scanf("%s",s+1);n=strlen(s+1);

int len=0,p=1,c;

for(int i=1;i<=cnt;i++)

}

\(code\ below:\)

#include #define ll long long

using namespace std;

const int maxn=400000+10;

int n,a[maxn],b[maxn],last,cnt,ch[maxn][26],fa[maxn],l[maxn],siz[maxn];

char s[maxn];ll sum[maxn],ans;

void insert(int c)

} siz[q]=1;

}int main()

} printf("%lld\n",ans);

return 0;

}

字尾自動機 SAM 學習筆記

參考資料 hihocoder1441 hihocoder1445 史上最通俗的字尾自動機詳解 練習題hihocoder1449 hihocoder1457 hihocoder1465 hihocoder1413 筆記 字串 aab 模板struct suffixautomaton int q ch ...

字尾自動機SAM

原理詳細的可以看史上最通俗的字尾自動機詳解 想看懂還是要花很久。實現 include include using namespace std const int maxn 2000010 struct node nodes maxn int las 1 tot 1 char st maxn void...

SAM 字尾自動機

好文 luogup3804 定義.對給定字串s的字尾自動機是乙個最小化確定有限狀態自動機,它能夠接收字串s的所有字尾。對給定字串s的字尾自動機是乙個最小化確定有限狀態自動機,它能夠接收字串s的所有字尾。某一狀態t 0被稱作初始狀態,由它能夠到達其餘所有狀態。自動機中的所有轉移 即有向邊 都被某種符號...