NOIp2020 T2 字串匹配 題解
NOIp2020 T2 字串匹配 題解
題目大意
定義\(A^1 = A\), \(A^i=A^{i-1}A\) ,如\(A=abc\)則\(A^{3}=abcabcabc\)
定義\(f(S)\)為字串\(S\)中出現奇數次的字元的數量,如\(A=abbc\),\(f(A)=2\)
給定\(S\),求滿足\(S=(AB)^iC\)且\(f(A)\le f(C)\)的方案數
題解(kmp)
首先我們需要知道一個東西
最小迴圈元長度 \(len = i - nxt[i]\) (\(nxt[i]\)為kmp中求出的失配陣列,具體是為什麼,自己想想,顯而易見)
於是我們從二開始列舉 \(i\) ,只要現在列舉到的\(S\)
先預處理出每個\(C\)中出現奇數次的字元數,時間複雜度\(O(n)\),還得跑一次kmp,求出\(nxt\)陣列,時間複雜度\(O(n)\)
考慮列舉\(AB\)串長度.
對\(S=ABC\)的情況統計答案
然後重複\(AB\)串,對於每個\(S=(AB)^jC\)的情況,如果符合要求,累加答案,否則顯而易見,若\(S!=(AB)^iC\)則\(S!=(AB)^{i+1}C\)必成立,退出迴圈即可.
總複雜度為\(O(Tn(26+1/n+2/n+...+n/n)) = O(T(nlogn + 26n))\)
需要注意的
-
列舉 \(AB\) 串長度從\(2\)-> \(n-1\).
-
統計答案時,所有滿足\(f(A') \le f(C)\)的串\(A'\)都會有\(1\)的貢獻,所以我們可以陣列\(c[p]\)表示當現在\(f(C)=p\)時,有多少個\(A'\)滿足條件.可以用以下方法\(O(26)\)複雜度求出
for(int i = tmp; i <= 26; ++i) c[i]++; // tmp 表示從現在A串中出現奇數次的字元的數量
-
重複\(AB\)串可以用以下方法求出
for (int j = i * 2; j < n; j += i) { // i為列舉的AB串長度 if(i % (j - nxt[j]) == 0 && j / (j - nxt[j]) > 1) { ans += c(tot[j + 1]); } else break; }
題解(hash)
和kmp的只有判斷\(S=(AB)^iC\)是否成立時不同.判斷方法如下
for (int j = i * 2; j < n; j += i) { // i為列舉的AB串長度
if((f[j] - f[j - i] * pw[i] % mod + mod) % mod == f[i]) {
ans += c(tot[j + 1]);
} else break;
} // f[x]表示從1到x的字串的hash結果 pw[x]表示hash的底數如131,1331的x次結果 mod為一個大質數
總複雜度\(O(T(26n+nlogn))\)但常數略大
題解(exkmp) -- 標準\(O(n)\)做法
不會,以後學了再補.