2019.01.26 codeforces 528D. Fuzzy Search(fft)

  • Post category:other

2019.01.26 codeforces 528D.Fuzzy Search(fft)的完整攻略

2019.01.26 codeforces 528D.Fuzzy Search(fft)是一道使用快速傅里叶变换(FFT)解决的字符串匹配问题。本文将提供该题的完整攻略,包括以下内容:

  1. 题目描述
  2. 解题思路
  3. 代码实现
  4. 示例1:输入样例
  5. 示例2:输出样例

题目描述

给定一个文本串T和一个模式串P,要求在T中找到所有与P相似的子串,其中相似的定义为:两个字符串的编辑距离不超过k。

解题思路

该题可以使用FFT算法解决。具体思路如下:

  1. 将T和P分别转换为多项式A和B。
  2. 对A和B进行点值表示。
  3. 将A和B的点值表示相乘得到C的点值表示。
  4. 对C的点值表示进行插值,得到C的系数表示。
  5. 对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)的完整攻略。