BZOJ4259: 残缺的字符串(FFT 字符串匹配)
题意
Sol
知道FFT能做字符串匹配的话这就是个裸题了吧。。
考虑把B翻转过来,如果\(\sum_{k = 0}^M (B_{i - k} - A_k)^2 * B_{i-k}*A_k = 0\)
那么说明能匹配。然后拆开三波FFT就行了
/*
*/
#include<bits/stdc++.h>
#define LL long long
const int MAXN = 1e6 + 10, INF = 1e9 + 7;
using namespace std;
inline int read() {
char c = getchar(); int x = 0, f = 1;
while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int N, M;
LL g[MAXN], f[MAXN];
char sa[MAXN], sb[MAXN];
int ta[MAXN], tb[MAXN], a[MAXN], b[MAXN], rev[MAXN], lim;
LL sqr2(int x) {return 1ll * x * x;}
LL sqr3(int x) {return 1ll * x * x * x;}
const double PI = acos(-1);
struct com {
double x, y;
com operator * (const com &rhs) const {
return {x * rhs.x - y * rhs.y, x * rhs.y + y * rhs.x};
}
com operator + (const com &rhs) const {
return {x + rhs.x, y + rhs.y};
}
com operator - (const com &rhs) const {
return {x - rhs.x, y - rhs.y};
}
}A[MAXN], B[MAXN];
void FFT(com *A, int lim, int type) {
for(int i = 0; i < lim; i++) if(i < rev[i]) swap(A[i], A[rev[i]]);
for(int mid = 1; mid < lim; mid <<= 1) {
com wn = {cos(PI / mid), type * sin(PI / mid)};
for(int i = 0; i < lim; i += (mid << 1)) {
com w = {1, 0};
for(int j = 0; j < mid; j++, w = w * wn) {
com x = A[i + j], y = w * A[i + j + mid];
A[i + j] = x + y;
A[i + j + mid] = x - y;
}
}
}
if(type == -1) {
for(int i = 0; i <= lim; i++) A[i].x /= lim;
}
}
void mul(int *b, int *a) {
memset(A, 0, sizeof(A)); memset(B, 0, sizeof(B));
for(int i = 0; i < N; i++) B[i].x = b[i];
for(int i = 0; i < M; i++) A[i].x = a[i];
FFT(B, lim, 1);
FFT(A, lim, 1);
for(int i = 0; i < lim; i++) B[i] = B[i] * A[i];
FFT(B, lim, -1);
for(int i = M - 1; i <= N; i++)
f[i] += round(B[i].x);
}
signed main() {
//freopen("2.in", "r", stdin); freopen("b.out", "w", stdout);
M = read(); N = read();
scanf("%s %s", sa, sb);
for(int i = 0; i < M; i++) ta[i] = (sa[i] == '*' ? 0 : sa[i] - 'a' + 1);
for(int i = 0; i < N; i++) tb[i] = (sb[i] == '*' ? 0 : sb[i] - 'a' + 1);
reverse(tb, tb + N);
int len = 0; lim = 1;
while(lim <= N + M) len++, lim <<= 1;
for(int i = 0; i < lim; i++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << len - 1);
for(int i = 0; i < N; i++) b[i] = sqr3(tb[i]);
for(int i = 0; i < M; i++) a[i] = ta[i];
mul(b, a);
for(int i = 0; i < N; i++) b[i] = -2 * sqr2(tb[i]);
for(int i = 0; i < M; i++) a[i] = sqr2(ta[i]);
mul(b, a);
for(int i = 0; i < N; i++) b[i] = tb[i];
for(int i = 0; i < M; i++) a[i] = sqr3(ta[i]);
mul(b, a);
int ans = 0;
for(int i = M - 1; i < N; i++)
if(!f[i]) ans++;
printf("%d\n", ans);
for(int i = N - 1; i >= M - 1; i--)
if(!f[i])
printf("%d ", N - i);
return 0;
}
/*
3 7
a*b
aebr*ob
*/
BZOJ4259: 残缺的字符串(FFT 字符串匹配)的更多相关文章
- P4173 残缺的字符串(FFT字符串匹配)
P4173 残缺的字符串(FFT字符串匹配) P4173 解题思路: 经典套路将模式串翻转,将*设为0,设以目标串的x位置匹配结束的匹配函数为\(P(x)=\sum^{m-1}_{i=0}[A(m-1 ...
- BZOJ4259:残缺的字符串(FFT)
Description 很久很久以前,在你刚刚学习字符串匹配的时候,有两个仅包含小写字母的字符串A和B,其中A串长度为m,B串长度为n.可当你现在再次碰到这两个串时,这两个串已经老化了,每个串都有不同 ...
- Luogu P4173 残缺的字符串-FFT在字符串匹配中的应用
P4173 残缺的字符串 FFT在字符串匹配中的应用. 能解决大概这种问题: 给定长度为\(m\)的A串,长度为\(n\)的B串.问A串在B串中的匹配数 我们设一个函数(下标从\(0\)开始) \(C ...
- luoguP4173 残缺的字符串 FFT
luoguP4173 残缺的字符串 FFT 链接 luogu 思路 和昨天做的题几乎一样. 匹配等价于(其实我更喜欢fft从0开始) \(\sum\limits_{i=0}^{m-1}(S[i+j]- ...
- 【BZOJ4259】残缺的字符串 FFT
[BZOJ4259]残缺的字符串 Description 很久很久以前,在你刚刚学习字符串匹配的时候,有两个仅包含小写字母的字符串A和B,其中A串长度为m,B串长度为n.可当你现在再次碰到这两个串时, ...
- BZOJ4259 残缺的字符串 【fft】
题目 很久很久以前,在你刚刚学习字符串匹配的时候,有两个仅包含小写字母的字符串A和B,其中A串长度为m,B串长度为n.可当你现在再次碰到这两个串时,这两个串已经老化了,每个串都有不同程度的残缺. 你想 ...
- BZOJ4259残缺的字符串
题目描述 很久很久以前,在你刚刚学习字符串匹配的时候,有两个仅包含小写字母的字符串A和B,其中A串长度为m,B串长度为n.可当你现在再次碰到这两个串时,这两个串已经老化了,每个串都有不同程度的残缺. ...
- CF528D Fuzzy Search 和 BZOJ4259 残缺的字符串
Fuzzy Search 给你文本串 S 和模式串 T,求 S 的每个位置是否能模糊匹配上 T. 这里的模糊匹配指的是把 T 放到 S 相应位置上之后,T 中每个字符所在位置附近 k 个之内的位置上的 ...
- 洛谷 P4173 残缺的字符串 (FFT)
题目链接:P4173 残缺的字符串 题意 给定长度为 \(m\) 的模式串和长度为 \(n\) 的目标串,两个串都带有通配符,求所有匹配的位置. 思路 FFT 带有通配符的字符串匹配问题. 设模式串为 ...
随机推荐
- 项目中使用同一dll的不同版本
在一个项目中,因为使用了一些插件,这些插件使用了不同版本的log4net,有1.2版本,有2.0版本的.当运行的时候发生冲突. 解决办法:在config中加入如下的配置 <dependentAs ...
- 背水一战 Windows 10 (73) - 控件(控件基类): UIElement - 拖放的基本应用, 手动开启 UIElement 的拖放操作
[源码下载] 背水一战 Windows 10 (73) - 控件(控件基类): UIElement - 拖放的基本应用, 手动开启 UIElement 的拖放操作 作者:webabcd 介绍背水一战 ...
- asp.net对接拼多多
asp.net对接拼多多视频地址:https://www.bilibili.com/video/av43512047/?p=7
- ng 的 ng-repeat(对象) 把对象的 key 和value 都拿出来 循环
对象的repeat 是这种形式
- Java匹马行天下之JavaSE核心技术——面向对象
面向对象 注: 看此篇时强烈建议有一定的面向对象思想基础,有一定的基础后先翻到下面看第九条: 9.面向对象: 从未封装→封装→继承→多态→抽象类→接口的代码演变 按这个逻辑去看,,哪有不理解 ...
- Linux下安装mysql5.7
Linux下安装mysql5.7 首先准备好mysql5.7.17的安装包,安装包放在 /data/software 目录下 进入到 /usr/local 目录下,解压mysql安装包 命令: ...
- maven 下载镜像文件卡,下载pom文件慢的问题
问题原因: maven默认的镜像库URL为 http://maven.net.cn/content/groups/public/ 由于网络原因,可能导致响应速度超级慢,或者无法效应: 解决方法: 配置 ...
- Maven - 实例-2-使用本地仓库中的依赖包
Maven引入构建包的流程 执行mvn compile命令编译源代码,如果编译过程中需要用到其他的包, maven将会在pom.xml文件中查找是否引入该依赖包的坐标. 示例: <depende ...
- day 75vue 脚手架学习 脚手架的使用
前情提要: vue 自定化开发工具 (vue-cli的使用) 一:安装脚手架,以及准备 1: 下载地址, https://nodejs.org/en/download/ 2:如果下载成功,在cmd ...
- [HAOI2017] 新型城市化
给出的图中恰包含2个团,则图的补图为一个二分图,其最大独立集为原图的最大团. 我们知道,二分图的最大独立集=V-最小顶点覆盖,最小顶点覆盖=最大匹配. 问题转化为:计算删去后最大匹配减小的边集. 所以 ...