用SAM實現字尾排序

2022-05-09 10:24:09 字數 1488 閱讀 9832

因為本人幾乎不會字尾陣列,所以遇到這種sa的模板題也要拿sam解決。

還是有一點思維難度的。

首先按照國際慣例,建反串的sam。

然後對於這個反串,我們考慮兩個字首哪乙個字典序小:因為是串是反的,所以要從後往前比較,那麼第乙個不相同的字元一定是兩個字首在字尾樹上的節點的lca的前一位。記其中乙個節點的任意乙個endpos的位置是\(end[i]\),lca的長度是\(len[x]\),那麼這個字元就是\(s[n - (end[i] - len[x])]\)。

這樣對於字尾樹上的每乙個節點,定義\(tp[i] = s[n - (end[i] - len[link[i]])] - 'a'\),然後以\(tp[i]\)為關鍵字進行基數排序就好了。

最後建出一棵新的樹,在上面dfs一遍即可。

luogu的板兒字符集太大,會mle,用map又tle了,而且不想手寫雜湊表,於是就沒放鏈結。

#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;

#define enter puts("")

#define space putchar(' ')

#define mem(a, x) memset(a, x, sizeof(a))

#define in inline

#define fore(i, x, y) for(int i = head[x], y; ~i && (y = e[i].to); i = e[i].nxt)

typedef long long ll;

typedef double db;

const int inf = 0x3f3f3f3f;

const db eps = 1e-8;

const int maxn = 1.1e6 + 5;

inline ll read()

inline void write(ll x)

in void myfile()

int n;

char s[maxn];

int ans[maxn], acnt = 0;

struct edge

e[maxn << 1];

int head[maxn << 1], ecnt = -1;

in void addedge(int x, int y)

; head[x] = ecnt;

}struct sam

in void insert(int c, int x)

}las = now;

} int tp[maxn << 1], pos[maxn << 1], buc[maxn << 1];

in void solve()

in void dfs(int now)

in void _print()

}s;int main()

字尾自動機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被稱作初始狀態,由它能夠到達其餘所有狀態。自動機中的所有轉移 即有向邊 都被某種符號...

SAM 字尾自動機

這玩意還真的好玄學,看了半天,也就看了個大概吧 確實很妙 總算理解了parent樹,但是關於sam的dag的性質的證明並沒有看太懂,也沒有特別明白。update 又看了一會,原來是自己把定義搞錯了,字尾自動機其實是在滿足以下條件的最簡狀態,主要是難構造,掌握構造 就好了,證明就不管了c。條件如下 摘...