LG P4173 残缺的字符串
\(\text{Problem}\)
大概就是带通配符的字符串匹配问题,输出所有比配位置
\(1\le n \le 3\times 10^5\)
\(\text{Solution}\)
这是 \(FFT\) 在字符串匹配中的应用
默认下标以 \(0\) 开始,记通配符数值为 \(0\)
\(A\) 为文本串,考虑 \(A\) 从某一位 \(i\) 开始与 \(B\) 的匹配结果
构造一个函数描述这个结果 \(F_i = \sum_{j=0}^{m-1} (A_{i+j}-B_j)^2 A_{i+j} B_j\)
\(F_i = 0\) 则 \(i\) 这个开始匹配位是成功的
我们要计算每个 \(F_i\),这还是不高效
但考虑把 \(B\) 翻转,\(F_i = \sum_{j=0}^{m-1} (A_{i+j}-B_{m-j-1})^2 A_{i+j} B_{m-j-1}\)
发现 \(A,B\) 小标加起来恒为 \(i+m-1\) !
这是多项式卷积的形式!
那我们就考虑把 \(A,B\) 当做一个多项式,\(F(x)=A(x)B(x)\)
这里的 \(F(x)\) 第 \(i+m-1\) 项的系数就是原来 \(F_i\) 的结果
这样就可以 \(O(n \log n)\) 做匹配了
\(\text{Code}\)
#include <cstdio>
#include <iostream>
#include <algorithm>
#define IN inline
#define RE register
using namespace std;
typedef long long LL;
const int N = 1e6 + 1e5, P = 998244353, g = 3;
int n, m, A[N], B[N], rev[N];
LL a[N], b[N], F[N];
char s[N];
IN int fpow(LL x, int y){LL s = 1; for(; y; y >>= 1, x = x * x % P) if (y & 1) s = s * x % P; return s;}
IN void NTT(LL *a, int lim, int inv)
{
if (lim == 1) return;
for(RE int i = 0; i < lim; i++) if (i < rev[i]) swap(a[i], a[rev[i]]);
for(RE int mid = 1; mid < lim; mid <<= 1)
{
int I = fpow(g, (P - 1) / (mid << 1));
if (inv == -1) I = fpow(I, P - 2);
for(RE int i = 0; i < lim; i += (mid << 1))
{
LL W = 1;
for(RE int j = 0, x, y; j < mid; j++, W = W * I % P)
x = a[i + j], y = W * a[i + j + mid] % P,
a[i + j] = (x + y) % P, a[i + j + mid] = (x - y + P) % P;
}
}
}
int main()
{
scanf("%d%d%s", &m, &n, s);
for(RE int i = 0; i < m; i++) if (s[i] == '*') A[i] = 0; else A[i] = s[i] - 'a' + 1;
scanf("%s", s);
for(RE int i = 0; i < n; i++) if (s[i] == '*') B[i] = 0; else B[i] = s[i] - 'a' + 1;
int lim = 1; while (lim < n + m - 1) lim <<= 1;
int bit = 0; while ((1 << bit) < lim) ++bit;
for(RE int i = 0; i < lim; i++) rev[i] = (rev[i>>1]>>1) | ((i&1)<<(bit-1));
reverse(A, A + m);
for(RE int i = 0; i < lim; i++) a[i] = A[i] * A[i] * A[i], b[i] = B[i];
NTT(a, lim, 1), NTT(b, lim, 1);
for(RE int i = 0; i < lim; i++) F[i] = a[i] * b[i] % P;
for(RE int i = 0; i < lim; i++) b[i] = B[i] * B[i] * B[i], a[i] = A[i];
NTT(a, lim, 1), NTT(b, lim, 1);
for(RE int i = 0; i < lim; i++) F[i] = (F[i] + a[i] * b[i] % P) % P;
for(RE int i = 0; i < lim; i++) a[i] = A[i] * A[i], b[i] = B[i] * B[i] % P;
NTT(a, lim, 1), NTT(b, lim, 1);
for(RE int i = 0; i < lim; i++) F[i] = (F[i] - a[i] * b[i] * 2 % P + P) % P;
NTT(F, lim, -1); int inv = fpow(lim, P - 2);
for(RE int i = 0; i < lim; i++) F[i] = F[i] * inv % P;
int ans = 0;
for(RE int i = m - 1; i < n; i++) if (!F[i]) ++ans;
printf("%d\n", ans);
for(RE int i = m - 1; i < n; i++) if (!F[i]) printf("%d ", i - m + 2);
}
LG P4173 残缺的字符串的更多相关文章
- 洛谷 P4173 残缺的字符串 (FFT)
题目链接:P4173 残缺的字符串 题意 给定长度为 \(m\) 的模式串和长度为 \(n\) 的目标串,两个串都带有通配符,求所有匹配的位置. 思路 FFT 带有通配符的字符串匹配问题. 设模式串为 ...
- Luogu P4173 残缺的字符串-FFT在字符串匹配中的应用
P4173 残缺的字符串 FFT在字符串匹配中的应用. 能解决大概这种问题: 给定长度为\(m\)的A串,长度为\(n\)的B串.问A串在B串中的匹配数 我们设一个函数(下标从\(0\)开始) \(C ...
- P4173 残缺的字符串(FFT字符串匹配)
P4173 残缺的字符串(FFT字符串匹配) P4173 解题思路: 经典套路将模式串翻转,将*设为0,设以目标串的x位置匹配结束的匹配函数为\(P(x)=\sum^{m-1}_{i=0}[A(m-1 ...
- P4173 残缺的字符串 fft
题意:给你两个字符串,问你第一个在第二个中出现过多少次,并输出位置,匹配时是模糊匹配*可和任意一个字符匹配 题解:fft加速字符串匹配; 假设上面的串是s,s长度为m,下面的串是p,p长度为n,先考虑 ...
- 洛谷P4173 残缺的字符串(FFT)
传送门 话说为什么字符串会和卷积扯上关系呢……到底得脑洞大到什么程度才能想到这种东西啊……大佬太珂怕了…… 因为通配符的关系,自动机已经废了 那么换种方式考虑,如果两个字符串每一位对应的编码都相等,那 ...
- 洛谷P4173 残缺的字符串
题目大意: 两个带通配符的字符串\(a,b\),求\(a\)在\(b\)中出现的位置 字符串长度\(\le 300000\) 考虑魔改一发\(kmp\),发现魔改不出来 于是考虑上网搜题解 然后考虑\ ...
- [Luogu P4173]残缺的字符串 ( 数论 FFT)
题面 传送门:洛咕 Solution 这题我写得脑壳疼,我好菜啊 好吧,我们来说正题. 这题.....emmmmmmm 显然KMP类的字符串神仙算法在这里没法用了. 那咋搞啊(或者说这题和数学有半毛钱 ...
- luogu P4173 残缺的字符串
传送门 两种做法,一种是依次考虑每种字符,然后如果某个位置是该字符或者是\(*\)对应的值就是1,否则是0,然后把第一个串倒过来,fft卷积起来,最后看对应位置的值是否为m 然而上面那个做法在字符集大 ...
- P4173 残缺的字符串
题目链接 题意分析 啥 ? ? ? \(FFT\)做字符串匹配 可是就是这样 我们定义匹配函数 我们定义\(A\)是匹配串 \(B\)是被匹配串 我们当前到达\(B\)串的\(x\)位置 \[P(x) ...
- 洛谷 P4173 残缺的字符串
(不知道xjb KMP可不可以做的说) (假设下标都以0开头) 对于有一定偏移量的序列的 对应位置 匹配或者数值计算的题,这里是有一种套路的,就是把其中一个序列翻转过来,然后卷积一下,所得到的新序列C ...
随机推荐
- Linux面试题2:网络IO模型 & IO多路复用
网络IO 先确定一下范围,我们讨论的都是网络IO,现阶段计算机早已经从CPU密集型转换成网络IO密集型,所以网络io的类型对于服务响应而言更重要. 五种IO模型 依据Unix的IO分类,网络IO分为五 ...
- 记一次windows10电脑连上wifi无法上网的解决问题
前言 今天下午同学的电脑能连上wifi,但是却上不了互联网 开始思考 首先想到的肯定是WiFi驱动问题,但是wifi能连上大部分的原因可能就不是驱动问题了,为了彻底排除这个因素,我用到了我的usb网卡 ...
- -webkit-box-orient:vertical 编译报错之autoprefixer问题
由于各大浏览器的兼容问题,autoprefixer 插件 就可以帮我们自动补齐前缀.它和 less.scss 这样的预处理器不同,它属于后置处理器. 预处理器:在打包之前进行处理 后置处理器:在代码打 ...
- SSH(二)框架配置文件
在引入了宽假所需要的jar包后,引入相应配置文件. 一.Struts2的配置文件: 1.Struts2的黑心过滤器,在web.xml中引入: <!-- struts2框架的核心过滤器 clas ...
- services资源+pod详解
services资源+pod详解 一.Service 虽然每个Pod都会分配一个单独的Pod IP,然而却存在如下两问题: Pod IP 会随着Pod的重建产生变化 Pod IP 仅仅是集群内可见的虚 ...
- vulnhub靶场渗透实战12-driftingblues2
vbox导入,网络桥接. 靶机下载地址:https://download.vulnhub.com/driftingblues/driftingblues2.ova 一:信息收集 1:主机发现. 2: ...
- 【RocketMQ】主从模式下的消费进度管理
在[RocketMQ]消息的拉取一文中可知,消费者在启动的时候,会创建消息拉取API对象PullAPIWrapper,调用pullKernelImpl方法向Broker发送拉取消息的请求,那么在主从模 ...
- 用 while 生成猜数字
import java.util.Random; import java.util.Scanner; public class zy2 { public static void main(String ...
- Java基础之常用类(String类)
String 类 定义 String 类代表字符串.Java 程序中的所有字符串字面值(如 "abc" )都作为此类的实例实现.我们可以将字符串看作是String, 但是严格意义上 ...
- SAP-FI模块 如何处理自动生成会计凭证增强
一. 相关问题概览 1. 固定资产业务过渡科目摘要增强功能-F-02 需用表BKPF.BSEG.T001.通过BUKRS.BELNR.GJAHR三个字段相等关联BKPF与BSEG.通过BKPF ...