暴力NTT

黄一肯 发表于 2年前 · 关联问题 字符串模糊匹配

对每个字符,做一遍匹配的NTT, 即设每个位置能匹配的值为f_i, 那么f_i = s_i + j == t_j(0 < j < t.size() ),然后每个字符都匹配一下,加到一起,暴力枚举对于位置i, 是否存在f_i + k >= t.size()就行

我的ntt板子常数大,换个常数小或者用fft应该就能过//我直接玄学剪枝跑出来的

#include <bits/stdc++.h> #define endl '\n' #define pb push_back using namespace std; using ll = long long; using db = double; using pii = pair<int , int>; const int maxn = 4e6 + 10; int zm[220][2]; const int mod = 998244353; const int G = 3; int n,m,L,R[maxn]; int A[maxn],B[maxn]; ll qpow(ll a,ll b) { ll ans = 1; while(b>0) { if(b&1) ans = ans*a%mod; b>>=1; a = a*a%mod; } return ans%mod; } void NTT(int *a,int f) { for(int i = 0; i < n; i++) { if(i < R[i]) swap(a[i],a[R[i]]); } for(int i = 1; i < n; i <<= 1) { ll gn = qpow(G,(mod - 1) / (i << 1)); for(int j = 0; j < n; j += (i << 1)) { ll g = 1; for(int k = 0; k < i; k++, g = g * gn % mod) { int x = a[j + k], y = g * a[j + k + i] % mod; a[j + k] = (x + y) % mod; a[j + k + i] = (x - y + mod) % mod; } } } if(f==1) return; int inv = qpow(n,mod - 2); reverse(a + 1,a + n); for(int i = 0; i < n; i++) a[i] = 1ll * a[i] * inv % mod; } void solve(int *A,int *B) { m = n + m; L = 0; for(n = 1; n <= m; n <<= 1) L++; for(int i = 0; i < n; i++) R[i] = (R[i >> 1] >> 1) | ((i & 1) << (L - 1)); NTT(A,1); NTT(B,1); for(int i = 0; i < n; i++) A[i] = 1ll * A[i] * B[i] % mod; NTT(A,-1); } int ans[maxn]; int main() { ios::sync_with_stdio(false); cin.tie(0), cout.tie(0); int i, j, k; cin >> k; string s, t; cin >> s >> t; for (auto c : s) zm[c][0]++; for (auto c : t) zm[c][1]++; int ty = 0; for (i = 0; i < 220; i++) { if (zm[i][0] && zm[i][1]) { for (j = 0; j < n; j++) A[j] = B[j] = 0; n = s.size(), m = t.size(); for (j = 0; j < n; j++) A[j] = s[j] == i; for (j = 0; j < m; j++) B[m - 1 - j] = t[j] == i; solve(A, B); int nn = s.size(), mm = t.size(); for (int t = mm - 1; t < nn; t++) ans[t - mm + 1] += A[t]; ty += 20 * nn; } if (ty > 80000000) break; } bool flag = 0; for (i = 0; i < s.size(); i++) if (ans[i] + k >= t.size()) flag = 1, cout << i + 1 << ' '; if (!flag) cout << -1; return 0; }