Fine-Grained学习笔记(1):卷积,FFT与花式字符串匹配

Fine-Grained,在算法复杂度理论中特指,对各类算法的复杂度,进行(相较于P与NP的粗粒度分类的)细粒度分类,例如,证明某问题存在 $n^2/ \log n$ 的算法.Fine-Grained是一个新兴领域,其研究前景可看作是计算机科学学科中的石墨烯与钙钛矿(误).

本系列主要参考University of Illinois at Urbana-Champaign的Timothy M. Chan在2022年秋季的课程,该课程的课堂笔记是公开的:CS 598 TMC, Fall 2022 (illinois.edu)

问题:卷积

给定长度为 $n$ 的序列 $A=<a_0,a_1,\cdots,a_{n-1}>,B=<b_0,b_1,\cdots,b_{n-1}>$,计算序列$C=<c_0,c_1,\cdots,c_{n-1}>$,其中$c_i=\Sigma_{k=0}^{i}a_kb_{i-k}$

等价问题:

给定两个多项式

$A(x)=a_{n-1}x^{n-1}+a_{n-2}x^{n-2}+\cdots+a_0$

$B(x)=b_{n-1}x^{n-1}+b_{n-2}x^{n-2}+\cdots+b_0$

计算$C(x)=A(x) \cdot B(x)=c_{2n-2}x^{2n-2}+\cdots+c_0$

朴素的算法:暴力,复杂度为$O(n^2)$

有无更好的办法?

Karatsuba算法(1960)

热身:

当$n=2$时,已知$a_0,a_1,b_0,b_1$,计算

$c_0=a_0b_0$

$c_1=a_1b_0+a_0b_1$

$c_2=a_1b_1$

这种方法需要4做4次乘法,但如果考虑

$c_1=(a_1+a_0)(b_1+b_0)-a_0b_0-a_1b_1$

便只需要做三次乘法.

那么对于任意$n$,使用分治法,将$A(x),B(x)$写成如下形式:

$A(x)=A_1(x)x^{n/2}+A_0(x)$

$B(x)=B_1(x)x^{n/2}+B_0(x)$

$A(x)B(x)=A_1(x)B_1(x)x^n+(A_1(x)B_0(x)+A_0(x)B_1(x))x^{n/2}+A_0(x)B_0(x)$

记$T(n)$为以该算法进行卷积运算的复杂度

$T(n)=3T(n/2)+O(n)$

$T(n)=O(n^{\log_23})\leq O(n^{1.59})$

Toom&Cook算法(1963)

热身:考虑$n=3$的情况

给定$a_0,a_1,a_2,b_0,b_1,b_2$,计算

$c_0=a_0b_0$

$c_1=a_0b_1+a_1b_0$

$c_2=a_0b_2+a_1b_1+a_2b_0$

$c_3=a_1b_2$

$c_4=a_2b_2$

共计需要9次乘法

更优的方法:令

$d_0=a_0b_0$

$d_1=(a_2+a_1+a_0)(b_2+b_1+b_0)$

$d_2=(4a_2+2a_1+a_0)(4b_2+2b_1+b_0)$

$d_3=(9a_2+3a_1+a_0)(9b_2+3b_1+b_0)$

$d_4=(16a_2+4a_1+a_0)(16b_2+4b_1+b_0)$

实际上,若令$d_k=(k^2a_2+ka_1+a_0)(k^2b_2+kb_1+b_0)$

$d_k=c_4k^4+c_3k^3+c_2k^2+c_1k+c_0 \qquad (k=0,\cdots 4)$

以高斯消元即可求得$c_0,\cdots,c_4$,该方法仅需5次乘法即可求解$n=3$的卷积

对于任意的$n$,利用上述方法进行三路分治,记运行时间为$T(n)$

$T(n)=5T(n/3)+O(n)$

$T(n)=O(n^{\log_3 5}) \leq O(n^{1.41})$

推广的分治法

总结上述两个算法,可以得到规律:规模为$r$的卷积求解问题,可以仅用$(2r-1)$次乘法求解.那么考虑对于规模为$n$的问题,对其进行$r$路分治求解,记其时间复杂度为$T(n)$

$T(n)=(2r-1)T(n/r)+O(n)$

$T(n)=O(n^{\log_r (2r-1)})$

$    \leq O(n^{\frac{\log(2r)}{\log r}})$

$    \leq O(n^{1+\frac{1}{\log r}})$

$    \leq O(n^{1+\epsilon})$

Cooley&Tukey 算法(快速傅立叶变换,FFT)

博主注:FFT虽然能够将卷积的复杂度降低到$O(n \log n)$,但运算过程中涉及了复变三角函数,必须假定无限精度实数的运算能在O(1)时间内完成,但此假设在计算复杂度领域内常用的RAM模型中并不成立,该算法的存在能否证明卷积运算的复杂度是$O(n \log n)$,此处存疑.

应用:$n$位大整数乘法

应用:3SUM问题(元素限制为有限整数)

记$[a,b]=\{a,a+1,\cdots,b\}$,即$a,b$之间的全体整数

记$[U]=[0,U]$,即$0,U$之间的全体整数.

给定$A,B,C\subseteq [U]$,$|A|,|B|,|C|=O(n)$,判断是否存在$a\in A,b\in B,c\in C$,使得$a+b=c$

朴素算法:

暴力,O(n^3)

尺取法:

稍微好一点,将$A,B$进行排序,定义两个指针分别指向$A$中最小值和$B$中最大值,比目标值小就把指向$A$的指针往右挪,否则就把指向$B$的指针往左挪,这样,对于每个$c\in C$,只需要做$O(n)$次操作.总时间复杂度$O(n^2)$

卷积法:

定义函数$f_a=\left\{\begin{matrix}
 1 & a\in A \\
 0 & a \notin A
\end{matrix}\right.$

$g_b=\left\{\begin{matrix}
 1 & b\in B \\
 0 & b \notin B
\end{matrix}\right.$

计算$h_c=\Sigma_{a=0}^{U-1}f_ag_{c-a}$,这一步卷积可以在$O(U \log U)$时间内解决,当$U \ll n^2$时,该方法较优.

应用:带通配符的字符串匹配

记$\Sigma$为字母表,给定模式串$P=p_1\cdots p_m \in (\Sigma \cup \{'?'\} )^*$,文本串$T=t_1\cdots t_n \in  (\Sigma \cup \{'?'\} )^*,(m<n)$,判断模式串是否出现于文本串中,用符号表示:

$\exists i \in [n], \forall j \in [m], p_j = t_{i+j}$ 或$p_j='?'$或$t_{i+j}='?'$

朴素算法:

暴力,$O(mn)$

KMP算法:

预处理模式串,寻找每个前缀字符串的后缀字符串,用于在失配发生时,跳过文本串中没必要匹配的部分.复杂度$O(n)$,但不能解决通配符的情况.

将字母表$\Sigma$中的所有字母映射到$[1:|\Sigma|]$中的数字,以便进行数学运算.将通配符$'?'$映射为$0$

卷积法:

考虑如下的匹配函数序列:

$f_i=\Sigma_{j=1}^{m}(p_j \cdot t_{i+j} \cdot (p_j - t_{i+j})^2)$

其意义是,若模式串第$j$位和文本串第$i+j$位匹配上(包括存在通配符和两个字符相等),则该单项值为$0$,否则为正数,若求和为0,则说明文本串从第$i$位开始和模式串匹配上了.

接下来将该表达式展开

$f_i=\Sigma_{j=1}^m(p_j^3t_{i+j})-2\Sigma_{j=1}^m(p_j^2t_{i+j}^2)+\Sigma_{j=1}^m(p_jt_{i+j}^3)$

将字符串$P$反转,记为$Q$,即$q_j=p_{m+1-j}$,表达式可写为如下形式

$f_i=\Sigma_{j=1}^m(q_{m+1-j}^3t_{i+j})-2\Sigma_{j=1}^m(q_{m+1-j}^2t_{i+j}^2)+\Sigma_{j=1}^m(q_{m+1-j}t_{i+j}^3)$

可以看出是三次卷积.

时间复杂度$O(n\log n)$

时间复杂度还可以优化到$O(n \log m)$,具体方法是将文本串$T$按照每块$m$个元素划分为$n/m$块,进行$n/m$次卷乘,每次计算$T$中的两个块与$P$的全部.

应用:字符串模糊匹配

定义:字符串的汉明距离

字符串$A,B\in \Sigma^{n}$,字符串的汉明距离定义为$|\{j:a_j \neq b_j\}|$,即两个字符串之间有多少个对应位置不相等.

给定模式串$P=p_1\cdots p_m \in \Sigma^*$,文本串$T=t_1\cdots t_{n}\in \Sigma^*$和限制$k$,判断是否存在$i$,使得$p_1\cdots p_m, t_{i+1}\cdots t_{i+m}$的汉明距离$\leq k$

朴素算法:

暴力,$O(mn)$

算法1:

定义函数序列$\mu_i=|\{j:p_j=t_{i+j}\}|$,计算这个函数

如何计算这个函数呢?对于所有的$c\in \Sigma$,定义

$\mu_i^{(c)}=|\{j:p_j=t_{i+j}=c\}|=\Sigma_j[p_j=c][t_{i+j}=c]$

用$O(n+m)$时间构造出$A^{(c)}=<a^{(c)}_1,\cdots , a^{(c)}_m>,B^{(c)}=<b^{(c)}_1,\cdots,b^{(c)}_n>,a^{(c)}_k=[p_{m+1-k}=c],b^{(c)}_k=[t_k=c]$,后,进行卷积即可.

计算完全部$\mu_i^{(c)}$之后,令$\mu_i=\Sigma_{c\in \Sigma}\mu_i^{(c)}$,然后遍历$\mu_i$,判断其中是否有连续$m$个元素之和$\geq m-k$.

总时间复杂度$O(|\Sigma|n \log n)$

但当$|\Sigma|$较大时又该怎么办呢?

Abrahamson算法(1987):

思路:将字母表中元素按出现次数高低进行分类

$\Sigma_H=\{c\in \Sigma : c \text{在模式串$P$中出现次数} > \Delta\}$

$\Sigma_L=\{c\in \Sigma : c \text{在模式串$P$中出现次数} \leq \Delta\}$

这样便保证了$|\Sigma_H|\leq m/\Delta$

1.高频情况

对于每个$c\in\Sigma_H$,使用卷积计算$\mu_i^{(c)}$,并令$\mu_i=\Sigma_{c\in \Sigma_H}\mu_i^{(c)}$,时间复杂度$O(|\Sigma_H|n\log n)=O(\frac{m}{\Delta}n \log n)$

2.低频情况

对于所有$l \in [1:n]$,若$t_l \in\Sigma_L$,那么对于所有满足$p_j=t_l$的$j$(总数$\leq \Delta$),令$\mu_{l-j}$加一.时间复杂度为$O(\Delta n)$

总运行时间$O(\frac{m}{\Delta} n \log n + \Delta n)$,令$\Delta=\sqrt{m\log n}$,总时间复杂度则为$O(n\sqrt{m\log n}+n \log n)= \widetilde{O}(n \sqrt{m})$

注:$\widetilde{O}(\cdot)$指相比$O(\cdot)$多出对数级.

Amir-Lewenstein-Porat(2004) $\widetilde{O}(n \sqrt{k})$

Gawrychowski-Vzanski(2018) $\widetilde{O}(n + \frac{nk}{\sqrt{m}})$

$\vdots$

接近于$O(n)$

应用:子集和问题

对于集合$A$,记$\Sigma(A)$为$A$中所有元素之和.

给定由$S$个正整数组成的集合$S$,目标值$T$,判断是否存在子集$R \subseteq S$使得$\Sigma(R)=T$

暴力枚举+尺取:

将$S$划分为两个大小为$n/2$的子集,枚举全部的子集和并归并排序,然后对以此法获得的两个长度为$O(2^{n/2})$的有序序列进行尺取,时间复杂度$O(2^{n/2})$

DP(动态规划):

时间复杂度$O(nT)$

一个用于求解可多次选取的子集和问题的思路:

观察:如果$S$中的元素可多次选取进$R$中,那么定义

$C^{(j)}[i]=\text{真,当且仅当存在多重集合}R\subseteq S, |R| \leq j,\Sigma(R)=i$

那么$c^{(j)}[i]$可以通过如下公式求出:

$C^{(j)}[i]=\vee_{i'=0}^{i}(C^{(j/2)}[i']\wedge C^{(j/2)}[i-i'])$

这又是一个卷积的形式,以此方法对原问题进行分治,总时间复杂度为$O(T\cdot\log T\cdot \log n)=\widetilde{O}(T)$(假定$n\leq T$,否则集合$S$中要么存在着比$T$还大的元素,可以一开始就排除掉,要么存在着重复元素,要么二者兼有)

但此方法对于一般的(不允许重复选取元素的)子集和问题无效

Bringmann算法(2017):

随机化地用于求解一般子集和问题的算法

引理1:

假定待求集合$S\subseteq [U]$中存在解$R\subseteq S$,且$|R|\leq k$,则存在一个随机化算法,可在$\widetilde{O}(k^2U)$时间内求得这个解.

证明:

记$\begin{pmatrix}a\\b\end{pmatrix}$为组合数,即在$a$个互不相同的物品中取出$b$个的方法数.

考虑如下事实:将$k$个球随机地放进$k^2$个桶中,每个桶中球的个数均$\leq 1$的概率$\geq 1/2$.("存在两个球被放进了同一个桶中"的概率 $\leq \begin{pmatrix}k\\2\end{pmatrix} \cdot \frac{1}{k^2}=\frac{1}{2}$)

那么,考虑将$S$随机地划分为$k^2$个子集,$S=S_{1}\cup S_{2} \cup \cdots \cup S_{k^2}$.

对于给定的$S_x,\cdots,S_{y}$定义$C_{S_x,\cdots,S_y}[i]$为真,当且仅当存在着子集$A$,$\Sigma(A)=i$,且$\forall j \in [x:y],|A \cup S_j| \leq 1$.

那么该序列可以通过如下方式求得:

$C_{S_1,\cdots,S_l}[i]=\vee_{i'=0}^{lU}(C_{S_1,\cdots,S_{l/2}}[i'] \wedge C_{S_{l/2+1},\cdots,S_l}[i-i'] )$

这是一个对长度为$O(lU)$的序列的卷积.用该卷积对$S_1,\cdots,S_{k^2}$进行分治.记求解子集个数为$l$的问题的复杂度为$T(l)$,对复杂度进行分析:

$T(l)=2T(l/2)+O(lU \log (lU))=O((l\log l)U\log(lU))=\widetilde{O}(lU)$

代入$l=k^2$,$T(k^2)=\widetilde{O}(k^2U)$

注意,该方法能否得出正确结果依赖于对于$S=S_1\cup S_2\cup \cdots \cup S_{k^2}$的划分,单次出错概率$\leq 1/2$的情况下可通过重复该算法$\log n$次将出错概率降低至$\leq 1/n$.

引理2:

引理1中的算法可优化至$\widetilde{O}(kU)$

证明:

考虑如下事实:把$k$个球放进$k$个桶里,每个桶中球的个数均$\leq n$个的概率$\geq 1-O(1/n)$(证明参照Chernoff限,待查)

随机地将$S$划分为$k$个子集,$S=S_{1}\cup S_{2} \cup \cdots \cup S_{k}$

定义$C_{S_x,\cdots,S_y}[i]$为真,当且仅当存在着子集$A$,$\Sigma(A)=i$,且$\forall j \in [x:y],|A \cup S_j| \leq \log n$

该序列可以通过如下方式求得:

$C_{S_1,\cdots,S_l}[i]=\vee_{i'=0}^{lU\log n}(C_{S_1,\cdots,S_{l/2}}[i'] \wedge C_{S_{l/2+1},\cdots,S_l}[i-i'] )$

这是一个对长度为$O(lU\log n)$的序列的卷积.

记求解子集个数为$l$的问题的复杂度为$T(l)$,同样分析其复杂度:

$T(1)$是在一个子集$S_j$中,枚举出至多$\log n$个元素所构成的子集和有哪些,这一步可以通过令$S'=S_j,k=\log n$并引入引理1中的算法得到,$T(1)=\widetilde{O}(U)$

$T(l)=2T(l/2)+O(lU\log n \log (lU))$

$T(l)=\widetilde{O}(lU)$

取$l=k$,$T(k)=\widetilde{O}(kU)$

由引理1,2推导出的算法:

对于所有的$u=1,2,4,\cdots,U$,以$S'=\{a_i \in S:a_i \in [u:2u-1]\},k=T/u$为输入,应用引理2中的算法,概率性地计算出$S'=\{a_i \in S:a_i \in [u:2u-1]\}$中的子集和(只保留$\leq T$的那些),单步时间复杂度为$\widetilde{O}(\frac{T}{u}\cdot 2u)=\widetilde{O}(T)$

对于这$O(\log U)$步中计算出的所有子集和进行归并,归并时间为$O(\log U \cdot T \log T)=\widetilde{O}(T)$

Jin&Wu算法(2019):

想法:多项式

求解子集和问题等同于求解$\Pi_{a\in S}(1+x^a) \mod x^{T+1}$,检查$x^{T}$项的系数.

记$exp(x)=e^x$

上式可写成$exp(\Sigma_{a\in S} \ln (1+x^a) ) \mod x^{T+1}$

考虑数学分析知识中的泰勒展开:

$\ln(1+x)=\Sigma_{i=1}^{\infty}\frac{(-1)^i}{i}x^i$

$\ln(1+x^a)=\Sigma_{i=1}^{T/a}\frac{(-1)^i}{i}x^{ai} \mod x^{T+1}$

对于每个$a$,共有$O(T/a)$项需要求和

总运行时间$O(T\Sigma_{a\in S}\frac{1}{a})=O(T \log T)$.

但直接计算这个式子的话是会出现分数项的,考虑随机选取质数$p$,在$Z_p$即模$p$的数域中进行运算,除法运算使用快速幂和费马小定理求模$p$的逆元,这样就变为了一个复杂度为$O(T \log^2 T)$的随机化算法.

posted @ 2023-04-23 21:40  Isakovsky  阅读(66)  评论(0编辑  收藏  举报