NTT/FFT与字符串匹配
字符串匹配问题,除了可以用、自动机等,有的还能利用实现。
本题中,对于每个在中符合的位置,都有
注意到,一般用加法实现,一般用乘法实现。
具体的,在本题中,我们定义,意为字符可以与匹配
那么(一个为,则等式成立)
则
即
令,有
转化成卷积形式,依次拆开,有:
那么当时,输出(是因为题目下标从开始)
Code
#include <bits/stdc++.h>
using namespace std;
const int mod = 998244353, g = 3, G = (mod + 1) / 3;
int n, m, t, k, tot, out[300005], p[1200005], a0[1200005], b0[1200005], a[1200005], b[1200005], res[1200005];
char s1[300005], s2[300005];
int read()
{
int x = 0; char ch = getchar();
while (ch < '0' || ch > '9') ch = getchar();
while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
return x;
}
int qpow(int base, int pw)
{
int s = 1;
while (pw)
{
if (pw & 1) s = 1ll * s * base % mod;
base = 1ll * base * base % mod;
pw >>= 1;
}
return s;
}
void g_l(int x)
{
t = 1, k = 0;
while (t <= x) t <<= 1, k ++ ;
for (int i = 0; i < t; i ++ ) p[i] = (p[i >> 1] >> 1) | ((i & 1) << (k - 1));
return;
}
void NTT(int *a, int o)
{
for (int i = 0; i < t; i ++ ) if (i < p[i]) swap(a[i], a[p[i]]);
for (int i = 1; i < t; i <<= 1)
{
int wn = qpow(o == 1 ? g : G, (mod - 1) / (i << 1));
for (int j = 0; j < t; j += (i << 1))
{
int w = 1;
for (int k = 0; k < i; k ++ , w = 1ll * w * wn % mod)
{
int p = a[j + k], q = 1ll * w * a[j + k + i] % mod;
a[j + k] = (p + q) % mod, a[j + k + i] = (p - q + mod) % mod;
}
}
}
if (o == -1)
{
int div = qpow(t, mod - 2);
for (int i = 0; i < t; i ++ ) a[i] = 1ll * a[i] * div % mod;
}
return;
}
int main()
{
n = read(), m = read(), scanf("%s", s1), scanf("%s", s2);
for (int i = 0; i < n; i ++ ) a0[i] = (s1[n - i - 1] == '*') ? 0 : s1[n - i - 1] - 'a' + 1;
for (int i = 0; i < m; i ++ ) b0[i] = (s2[i] == '*') ? 0 : s2[i] - 'a' + 1;
g_l(n + m);
for (int i = 0; i < t; i ++ ) a[i] = 1ll * a0[i] * a0[i] % mod * a0[i] % mod, b[i] = b0[i];
NTT(a, 1), NTT(b, 1);
for (int i = 0; i < t; i ++ ) res[i] = (res[i] + 1ll * a[i] * b[i] % mod) % mod;
for (int i = 0; i < t; i ++ ) a[i] = 1ll * a0[i] * a0[i] % mod, b[i] = 1ll * b0[i] * b0[i] % mod;
NTT(a, 1), NTT(b, 1);
for (int i = 0; i < t; i ++ ) res[i] = (res[i] - 2ll * a[i] * b[i] % mod + mod * 2ll) % mod;
for (int i = 0; i < t; i ++ ) a[i] = a0[i], b[i] = 1ll * b0[i] * b0[i] % mod * b0[i] % mod;
NTT(a, 1), NTT(b, 1);
for (int i = 0; i < t; i ++ ) res[i] = (res[i] + 1ll * a[i] * b[i] % mod) % mod;
NTT(res, -1);
for (int i = n - 1; i <= m - 1; i ++ ) if (!res[i]) out[ ++ tot] = i + 2 - n;
printf("%d\n", tot); for (int i = 1; i <= tot; i ++ ) printf("%d ", out[i]); putchar('\n');
return 0;
}
分类:
C-专题总结
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】