2019.01.26 codeforces 528D.Fuzzy Search(fft)的完整攻略
2019.01.26 codeforces 528D.Fuzzy Search(fft)是一道使用快速傅里叶变换(FFT)解决的字符串匹配问题。本文将提供该题的完整攻略,包括以下内容:
- 题目描述
- 解题思路
- 代码实现
- 示例1:输入样例
- 示例2:输出样例
题目描述
给定一个文本串T和一个模式串P,要求在T中找到所有与P相似的子串,其中相似的定义为:两个字符串的编辑距离不超过k。
解题思路
该题可以使用FFT算法解决。具体思路如下:
- 将T和P分别转换为多项式A和B。
- 对A和B进行点值表示。
- 将A和B的点值表示相乘得到C的点值表示。
- 对C的点值表示进行插值,得到C的系数表示。
- 对C的系数表示进行处理,得到所有与P相似的子串。
代码实现
以下是该题的代码实现:
import numpy as np
import cmath
def fft(a):
n = len(a)
if n == 1:
return a
wn = cmath.exp(2 * cmath.pi * 1j / n)
w = 1
a0 = a[::2]
a1 = a[1::2]
y0 = fft(a0)
y1 = fft(a1)
y = [0] * n
for k in range(n // 2):
y[k] = y0[k] + w * y1[k]
y[k + n // 2] = y0[k] - w * y1[k]
w *= wn
return y
def ifft(a):
n = len(a)
if n == 1:
return a
wn = cmath.exp(-2 * cmath.pi * 1j / n)
w = 1
a0 = a[::2]
a1 = a[1::2]
y0 = ifft(a0)
y1 = ifft(a1)
y = [0] * n
for k in range(n // 2):
y[k] = y0[k] + w * y1[k]
y[k + n // 2] = y0[k] - w * y1[k]
w *= wn
return y
def conv(a, b):
n = 1
while n < len(a) + len(b):
n *= 2
a += [0] * (n - len(a))
b += [0] * (n - len(b))
fa = fft(a)
fb = fft(b)
fc = [fa[i] * fb[i] for i in range(n)]
c = ifft(fc)
c = [int(round(c[i].real / n)) for i in range(n)]
return c
def fuzzy_search(T, P, k):
n = len(T)
m = len(P)
a = [1 if T[i] == P[j] else 0 for i in range(n) for j in range(m)]
b = [1 if abs(i - j) <= k else 0 for i in range(m) for j in range(m)]
c = conv(a, b)
ans = 0
for i in range(n - m + 1):
if c[i * m] > 0:
ans += 1
return ans
T = input()
P = input()
k = int(input())
ans = fuzzy_search(T, P, k)
print(ans)
示例1:输入样例
abacaba
aba
1
示例2:输出样例
3
以上是2019.01.26 codeforces 528D.Fuzzy Search(fft)的完整攻略。