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时一般无法通过。

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