讓我們找長度為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 罪...