链接:Forgiving Matching
题意:
给出两个字符串 S , T。长度分别为n , m( 1 ≤ m ≤ n ≤ 200000 1\leq m \leq n\leq 200000 1≤m≤n≤200000),现定义两字符串的 ans[k]为 :字符串S中包含多少个子串与T相似(相似的定义为两字符串最多k个位置不同)。现要求出所有的 ans[k] ( 0 ≤ k ≤ m 0\leq k \leq m 0≤k≤m)。
思路:
- 我们先来考虑如何暴力求解 , 如果我们固定 S 串,让T串往右匹配S的每一个子串 , 如果在匹配当前子串时有 x 个位置相同,那么就可以对答案 ans[m - x]到ans[m]都贡献 1,差分记录以下,最后求个前缀和就可以得到所有的答案。复杂度接近 o ( n ∗ m ) o(n * m) o(n∗m)
- 在暴力求法中,如果我们可以快速的知道 T 串匹配每一个子串时有多少个位置相同那么就能快速得到答案。所以我们可以预处理出 T 串移动 i 位的匹配数。也就是要求出对于T中的每一个字符,往右移动几位能在 S 中找到相同的字符或 * 。那就是对每一种字符都求出 S T 中所在位置的差值,就可以用FFT来求解了。类似于前几天牛客多校的 H Hash Function。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 5;
const int num = 200002;
const double Pi = acos(-1.0);
int r[maxn];
int vis[maxn];
int T, n , m;
char s1[maxn],s2[maxn];
int ans[maxn] , cnt[maxn];
struct Complex{
double x, y;