字尾自動機 Substrings

2021-10-08 10:36:15 字數 2191 閱讀 3683

讓我們找長度為x的子串出現的最大次數。我們先建立sam,然後把節點top序。我們知道endpos是一些出現相同次數和相同結束位置的集合。所以我們定義f

if_i

fi​為長度為i的子串出現的最大次數。我們因為知道長度f

i>=f

jf_i>=f_j

fi​>=f

j​,i

i<

j的時候,所以我們只需要更新f[l

en[i

]]

f[len[i]]

f[len[

i]]就可以了。f[l

en[i

]]=m

ax(e

ndpo

s[i]

,f[l

en[i

]]

)f[len[i]]=max(endpos[i],f[len[i]])

f[len[

i]]=

max(

endp

os[i

],f[

len[

i]])

。最後按照top序回去更新最大值。

#include

using

namespace std;

const

int maxn=

2e5+

5e4+10;

const

int maxc=27;

typedef

long

long ll;

struct suffix_automaton

// for(int i=1;i<=id;i++)

last = id =1;

//1表示root起始點 空集

}//sam建圖

void

add(

int c)

else

else

} last = x;

//更新最後處理的結點

} ll getsubnum()

void

gettp

(int len)

void

getendpos()

}void

solve

(int n)

for(

int i=id;i>=

1;i--

) dp[i]

=max

(dp[i+1]

,dp[i]);

for(

int i=

1;i<=n;i++

)printf

("%lld\n"

,dp[i]);

}void

llm(

char s,

int len)

else

ans=

max(ans,cnt);}

printf

("%d\n"

,ans);}

void

llm2

(char s,

int len)

else

dp[now]

=max

(dp[now]

,cnt);}

for(

int i=id;i>=

1;i--

)for

(int i=

1;i<=id;i++

) ans[i]

=min

(ans[i]

,dp[i]);

}void

get_llm2_ans()

/* void solve1()

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

// void solve1()

// }

// ll ans=0;

// for(int i=0;i<26;i++)

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

// }

/* void solve2()

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

}*/void

init_ans()

} sam;

char s[maxn]

;signed

main()

字尾自動機

基礎知識 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 罪...