ZOJ3891 K hash 字尾自動機SAM

2021-07-05 00:10:53 字數 990 閱讀 8639

題目:

題意:給出乙個整數k(<=32)和乙個長度50000以內由十進位制數構成的字串s,要求統計s的不重複子串所表示的數對k取模的結果。

本題屬於sam入門題,當時在做zoj月賽時還沒學,學完後發現很簡單。果然sam功能很強大。

題解:建造字尾自動機,按拓撲序從小到大進行dp,記錄到此節點取模得到d的方案數。

具體一點,y->num[(i*10+j)] += x->num[i] if trans(x,j)

特別注意0的情況,開頭不能有0,最優統計0的個數時,看root->go[0]是否存在。

最後從0到tot節點的方案數累加即可。

**:#include#include#include#includeusing namespace std;

const int maxn = 50000*2+10;

long long ans[34];

int k;

struct state

void init()

} *root , *last , *cur;

state statepool[maxn*2] , *first[maxn]={};

int tot = 0;

void init(int l)

void extend(int w)else

}last = np;

}void start(char *s)

tot = 1;

for(int it=1;it<=l;it++)}}

}for(int i=0;igo[0])

ans[0] += 1;

}char s[maxn];

int main(){

while(scanf("%s",s)!=eof){

scanf("%d",&k);

memset(ans,0,sizeof(ans));

start(s);

for(int i=0;i<=k-1;i++){

cout<

字尾自動機

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

字尾自動機

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

字尾自動機

基礎學習 簡潔明瞭的講解 總狀態數不超過2n 12n 1 2n 1 包括初始狀態 統計每個end po sendpos endpos 等價類出現位置數量時,要按長度從長到短的計算cnt cntcn t。那為什麼一定要從長到短呢?比如回文自動機就直接是按照節點編號從大到小計算cnt cntcn t 罪...