[加强版] Codeforces 835D Palindromic characteristics (回文自动机、DP)
題目鏈接: https://codeforces.com/contest/835/problem/D
題意: 一個回文串是\(1\)-回文的,如果一個回文串的左半部分和右半部分一樣且都是\(k\)-回文串(右半部分是指長度為該串長度除以二下取整的后綴),則該串為\((k+1)\)回文串,滿足該串是\(k\)回文串的最大\(k\)稱作該串的回文級別。給定一個串\(s\), 對于每一個\(k=1,2,...,n\)求出該串中有多少個位置不同的\(k\)-回文串。\(n\le 5\times 10^6\). (除數(shù)據(jù)范圍外與原題均相同)
題解: \(n^2\)的做法肯定是以子串為狀態(tài)進行dp, 但是顯然廢狀態(tài)太多了,只有回文串dp值非零,而一個串本質不同的回文串的個數(shù)是\(O(n)\)的。
所以,以本質不同的回文串作為狀態(tài)進行dp. 本質不同的回文串一一對應回文自動機上的節(jié)點。設\(f[x]\)表示\(x\)節(jié)點代表回文串的回文級別。
然后轉移方程顯然: 若\(x\)不存在長度為\([\frac{x}{2}]\)(中括號表示下取整)的回文后綴,則\(dp[x]=1\), 否則\(dp[x]\)等于那個回文后綴的\(dp\)值+1.
dp完之后,我們求的是本質不同,但是題目要求求位置不同,所以還需要再統(tǒng)計一下每個點的子樹大小。
時間復雜度\(O(n)\).
代碼 (Codeforces 835D AC)
#include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #define llong long long using namespace std;const int N = 1e6+2; const int LGN = 23; const int S = 26; int son[N+3][S+1]; int fail[N+3]; int len[N+3]; int sz[N+3]; int tsz[N+3]; char a[N+3]; int dp[N+3]; int bd[N+3]; int ord[N+3]; int buc[N+3]; llong ans[N+3]; int n,siz,lstpos;void initPAM() {siz = lstpos = 1; fail[0] = fail[1] = 1; len[1] = -1; len[0] = 0; bd[0] = 0; bd[1] = 1; }void insertchar(int id) {int p = lstpos;while(a[id]!=a[id-len[p]-1]) {p = fail[p];}if(!son[p][a[id]]){siz++; int u = siz,v = fail[p];while(a[id]!=a[id-len[v]-1]) {v = fail[v];}fail[u] = son[v][a[id]]; son[p][a[id]] = u; len[u] = len[p]+2;if(len[u]<=2) {bd[u] = fail[u];}else{bd[u] = bd[p];while(a[id]!=a[id-len[bd[u]]-1] || (len[bd[u]]+2)*2>len[u]){bd[u] = fail[bd[u]];}bd[u] = son[bd[u]][a[id]];}if(len[bd[u]]==(len[u]>>1)) {dp[u] = max(0,dp[bd[u]])+1;}else {dp[u] = 1;}}sz[son[p][a[id]]]++;lstpos = son[p][a[id]]; }int main() {initPAM();scanf("%s",a+1); n = strlen(a+1);for(int i=1; i<=n; i++) a[i]-=96;for(int i=1; i<=n; i++) {insertchar(i);}for(int i=2; i<=siz; i++) {buc[len[i]]++;}for(int i=1; i<=n; i++) {buc[i] += buc[i-1];}for(int i=siz; i>=2; i--) {ord[(buc[len[i]]--)+1] = i;}ord[0] = 1; ord[1] = 0;for(int j=siz; j>=2; j--){int u = ord[j];sz[fail[u]] += sz[u];}for(int j=2; j<=siz; j++){ans[dp[j]] += (llong)sz[j];}for(int j=LGN-1; j>=1; j--) ans[j] += ans[j+1];for(int i=1; i<=n; i++) printf("%I64d\n",ans[i]);return 0; }總結
以上是生活随笔為你收集整理的[加强版] Codeforces 835D Palindromic characteristics (回文自动机、DP)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BZOJ4044 Luogu P4762
- 下一篇: BZOJ 4278 [ONTAK2015