字尾自動機合集 I

2021-06-18 07:02:58 字數 3412 閱讀 6873

有關字尾自動機的理論和證明各路大神的部落格多如牛毛,就不細說。

貼圖太佔載入速度了,還是去看原版的解析吧

對於每個state點,father指向與該節點可接收相同字尾的節點,其表示的字串通常是當前節點表示字串的後面部分,

因此state->step - sate->father->step 代表從任一字尾串起始走到該狀態的路徑數

對每個狀態點減去父狀態的步驟數的和就是字串所有字串的數量

#include #include #include #include using namespace std;

const int maxn = 2010;

int ans[maxn][maxn];

char s[maxn];

struct node

int calc()

return step - fa->step;

}} *root, *tail, nodepool[maxn * 2], *cur;

void init()

int tot;

void insert ( int w )

if ( !p )

else

else}}

tail = np;

}int main()

}int q;

scanf ( "%d", &q );

while ( q-- )

}return 0;

}

每個step姑且認為是轉移到該狀態時可接收的最大字串

最長公共子串

#include #include #include #include using namespace std;

const int maxn = 100010;

char s[maxn];

struct node

} *root, *tail, nodepool[maxn << 1], *cur;

void init()

void insert ( int w )

if ( !p )

else

else}}

tail = np;

}int solve()

else

else

}res = max(sum, res);

} return res;

}int main()

scanf("%s", s);

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

}return 0;

}

菜鳥對sam的理解還是太弱了,借鑑了別人的**才搞懂

本題用sam來做,核心是記錄下到達每個state時能得到bi字串的最大長度。

再此還要解釋下,引入father指標的目的是最大化狀態的重用性,每個狀態的父節點表示的串 == 當前狀態所表示的字串最後幾位

因此,父節點的deep要更新為自身及子節點deep的最大值

每個節點deep - step 就表示為除去不符合要求串數量的後的值

#include #include #include #include using namespace std;

typedef long long ll;

const int maxn = 100010;

char s[maxn];

struct node

} *root, *tail, nodepool[maxn << 1], *cur;

void init()

void insert ( int w )

if ( !p )

else

else}}

tail = np;

}void update()

else

if ( p == null )

else

}p->deep = max ( p->deep, sum );

}}int p[maxn << 1]; node *op[maxn << 1];

int main()

for ( int i = 0; i < n; ++i )

ll res = 0;

memset ( p, 0, sizeof p );

for ( int i = 0; i < cur - root; ++i )

for ( int i = 1; i <= tail->step; ++i )

for ( int i = 0; i < cur - root; ++i )

for ( int i = cur - root - 1; i > 0; --i )

}else

}#ifdef __gnuc__

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

#else

printf ( "%i64d\n", res );

#endif

}return 0;

}

關鍵問題是字尾自動機狀態刪除,可行的辦法就是設定標記表示該狀態是否被刪除,且同一狀態的拷貝點也指向相同的標記

#include #include #include #include using namespace std;

const int maxn = 200020;

char s[maxn ];

int isdel[maxn], delcnt;

struct node

} *root, *tail, nodepool[maxn << 1], *cur, *mseq[maxn], *cnt;

void init()

int judge ( node *x )

void insert ( int w )

if ( !p )

else

else}}

tail = np;

}int flag, tl;

void dfs ( node *k, int l )

if ( l == tl )

if ( k->*** == cnt )

for ( int i = 0; !flag && i < 26; ++i )

}}int main()

scanf ( "%d", &n );

while ( n-- )

}else if ( c == 2 )

scanf ( "%d", &k );

flag = 0; tl = k;

dfs ( root, 0 );

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

}else}}

}return 0;

}

字尾自動機合集 II

在sam中,state ai nxt w stateb w const stateb fa step state ai step state ai nxt w stateb 利用拓撲排序,可構建所有子串在原串中出現的次數 sam中的每個狀態點都表示為從root出發走到該點所構成的子串,若其作為其他狀...

字尾自動機

基礎知識 step i 表示的是字串i在原字串中的位置。pareint i 表示root到parent i 的子串是root到i的最長字尾。字尾自動機遍歷可以得到原字串的所有子串。特殊技巧 一 字尾自動機的不同子串數有兩種求法 1.ans step i step parent i 1 i cnt 2...

字尾自動機

常用於處理字串問題,可以高效解決許多字串問題。有點像將乙個字串的所有字尾都建在乙個ac自動機上,但不同的是字尾自動機的節點數最多為2 n,因為它只記錄需要記錄的點,一些沒有記錄東西的點可以視為與下面有價值的節點並在一起,這樣大大降低了時間複雜度和空間複雜度。對於每乙個節點記錄它的後面加上每個字元後字...