[POI2006]OKR-Periods of Words
阿新 • • 發佈:2018-09-25
cst rds www 發現 += %s 一個 字符 poi 數組的求解,所以要在KMP之後求答案。
Description
Luogu3435
對一個字符串\(A\),定義其周期\(Q\)為,\(Q\)為\(A\)的前綴(\(Q!=A\))且\(A\)為\(QQ\)的前綴(\(A\)可以等於\(QQ\))。求一個字符串的所有前綴的最長周期的長度之和。
Solution
首先觀察周期的定義,可以發現,一旦該字符串有一個前綴等於該字符串的一個後綴,那麽這個字符串就是有周期的,與前後綴有關的那就是KMP了。而要求周期最長,就是要求該前綴最短,轉化問題之後就可以用KMP解決了。但是,sb的我竟然在KMP的過程中xjb亂跳,直接就跳到最短的了,可是這樣會掛啊!考慮這樣的一個字符串abacabac
,如果在KMP裏就處理答案的話就會影響next
哦對了,求答案的時候可以記憶化一下。
Code
#include <cstdio> typedef long long LL; const int N = 1e6 + 10; char s[N]; int nxt[N]; LL ans; int n; int main() { scanf("%d", &n); scanf("%s", s+1); nxt[0] = -1; for (int i = 1; i <= n; ++i) { int t = nxt[i-1]; while (t != -1 && s[t+1] != s[i]) t = nxt[t]; /* 這裏不能有這句話啊!!!!!!!!!!!!!!! if (t != -1) while (nxt[t] != -1 && s[nxt[t] + 1] == s[i]) t = nxt[t]; */ nxt[i] = t + 1; } for (int i = 1; i <= n; ++i) { int t = nxt[i]; while (nxt[t] > 0) t = nxt[t]; if (nxt[i]) nxt[i] = t; // 記憶化一下 if (t) ans += i - t; } printf("%lld\n", ans); return 0; }
[POI2006]OKR-Periods of Words