Codeforces1334G Substring Search【通配字符匹配問題】

題目描述:

給出字母排列pp以及字符串s,ts,t
ss中的字符cc可以匹配tt中的ccpcp_{c},求sstt中的出現位置。
n2105n\le2*10^5

題目描述:
法一:枚舉字符累加匹配數

枚舉一個字符cc,將ss中爲cc的位置設爲1,tt中匹配的位置設爲1,然後做卷積。
每個字符都做完後 ii 位置的值就是[is+1,i][i-|s|+1,i]匹配ss的位置個數,檢驗是否等於s|s|即可。
複雜度O(nlogn)O(\sum*n\log n)\sum是字符集大小,這裏是2626
不太能過,可以虛數部分利用起來減小2的常數。

法二:差異計算式求和

將每個位置的匹配信息寫作一個計算式,當且僅當匹配時爲0,其餘時候爲正數,那麼就只需要檢驗最後對應位置的和是否爲0即可。
此題中ss匹配t[l,r]t[l,r]計算式爲 i=0rl(sitl+i)2(psitl+i)2\sum_{i=0}^{r-l}(s_i-t_{l+i})^2*(p_{s_i}-t_{l+i})^2,將平方拆開之後做FFT。
拆開之後每一項形如 coef(siapsib)tl+iccoef*(s_i^a*p_{s_i}^b)*t_{l+i}^c,總共需要 9 次FFT 以及 2 個前綴和。
upd:實際上可以根據兩個位置的冪次和來FFT,比如把a+ba+b相同的合併在一起,然後乘上對應的cc,這樣只需要做 3 次FFT 和 2 個前綴和。
複雜度O(nlognC)O(n\log n*C)CC是計算式決定的常數。

如果將FFT改寫爲NTT,由於是在模意義下,可能被卡。可以選擇取兩個模數;或者更簡便的方法是將字符隨機一個[0,mod)[0,mod)以內的權值,這樣做的話甚至可以把計算式中的平方給去掉(相當於是在哈希了)。

法三:枚舉字符bitset匹配

FFT和bitset其實是在做差不多的事情,對每個字符預處理出一個bitset T[c]T[c]表示cc字符在 tt 中的出現位置,然後求出這個字符在 tt 中的匹配位置 match[c]match[c]。在此題中 mat[c]=T[c]  T[pc]mat[c]=T[c]~|~T[p_c]

然後用一個bitset ansbitset~ans記錄每個位置對ss的前ii個字符是否匹配,每次添加s[i]s[i]時,令ans&=match[s[i]]>>ians\&=match[s[i]]>>i,最後ansans的第ii位爲1就代表[i,i+s1][i,i+|s|-1]ss匹配了。

複雜度O(+nmw)O(預處理+\frac {nm}w),這個算法當n105n\ge10^5時一般無法通過。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章