Codeforce 432 D. Prefixes and Suffixes 解析(思維、字串、Z-Algo)
今天我們來看看CF432D
題目連結
題目
略,請直接看原題。
前言
實際上自己根本沒實作過Z-Algo,感覺很抖。
觀看更多正版原始文章請至petjelinux的blog
想法
首先看到了後綴和前綴的關係,就感覺和KMP或者Z-Algo脫不了關係。稍微複習一下KMP和Z-Algo的DP計算的意義,發現了基本上就是Z-Algo存的資料的應用。
對於第一個問題:有幾個後綴等於前綴,這顯然就是赤裸裸的用Z-Algo的資料。
對於第二個問題:只要觀察到,對於一個長度為\(l\)的前綴(等於後綴),任何\(Z[i]\ge l\)都會對這個子字串造成貢獻,也因此只要維護一個\(Z[i]\)的後綴和即可輕鬆得到答案。
注意,一般來說\(Z[0]=0\),因此最後我們需要自己改成\(Z[0]=length\)。
程式碼:
const int _n=1e5+10;
int t,n,Z[_n],LEN,ans[_n],cnt,c[_n];
string s;
main(void) {ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>s;LEN=s.length();n=LEN;
int L = 0, R = 0;
for (int i = 1; i < LEN; i++) {
if (i > R) {
L = R = i;
while (R < n && s[R-L] == s[R]) R++;
Z[i] = R-L; R--;
} else {
int k = i-L;
if (Z[k] < R-i+1) Z[i] = Z[k];
else {
L = i;
while (R < n && s[R-L] == s[R]) R++;
Z[i] = R-L; R--;
}
}
}
Z[0]=LEN;
rep(i,0,LEN)if(Z[i] and Z[i]>=LEN-i)ans[Z[i]]++;
rep(i,1,LEN+1)if(ans[i])cnt++;
cout<<cnt<<'\n';cnt=0;
rep(i,0,LEN)if(Z[i])c[Z[i]]++;
vector<PII> p;per(i,1,LEN+1){
cnt+=c[i];if(ans[i])p.pb({i,cnt});
}per(i,0,SZ(p))cout<<p[i].fi<<' '<<p[i].se<<'\n';
return 0;
}
標頭、模板請點Submission看
Submission