洛谷 P4173 残缺的字符串 (FFT)
题目链接:P4173 残缺的字符串
题意
给定长度为 \(m\) 的模式串和长度为 \(n\) 的目标串,两个串都带有通配符,求所有匹配的位置。
思路
FFT
带有通配符的字符串匹配问题。
设模式串为 \(p\),目标串为 \(t\),将两个串的内容都根据字母先后顺序映射到 \(1\) 到 \(26\)。
如果不带有通配符,那么 \(t\) 以第 \(k\) 位结束的长度为 \(|p|\) 的子串与 \(p\) 匹配时有
\]
如果带有通配符,只需将上式稍微改一下就行。
让两个串中的所有通配符映射到 \(0\),设匹配结果为 \(f\),则有
\]
接下来翻转 \(p\) 串 (\(FFT\) 的套路),设 \(r[|p| - i - 1] = p[i]\),则有
\]
下标加起来等于 \(k\),令 \(j = |p| - i - 1\),则
\]
展开后有
\]
用 \(FFT\) 分别求一下卷积即可。
代码
#include <bits/stdc++.h>
using namespace std;
const double PI = acos(-1);
const double eps = 1e-8;
typedef complex<double> Complex;
const int maxn = 2e6 + 10;
Complex p[maxn], t[maxn];
Complex a[maxn], b[maxn], c[maxn], d[maxn];
Complex ans[maxn];
string str;
int m, n;
int bit = 2, rev[maxn];
void get_rev(){
memset(rev, 0, sizeof(rev));
while(bit <= n + m) bit <<= 1;
for(int i = 0; i < bit; ++i) {
rev[i] = (rev[i >> 1] >> 1) | (bit >> 1) * (i & 1);
}
}
void FFT(Complex *a, int op) {
for(int i = 0; i < bit; ++i) {
if(i < rev[i]) swap(a[i], a[rev[i]]);
}
for(int mid = 1; mid < bit; mid <<= 1) {
Complex wn = Complex(cos(PI / mid), op * sin(PI / mid));
for(int j = 0; j < bit; j += mid<<1) {
Complex w(1, 0);
for(int k = 0; k < mid; ++k, w = w * wn) {
Complex x = a[j + k], y = w * a[j + k + mid];
a[j + k] = x + y, a[j + k + mid] = x - y;
}
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cin >> m >> n;
cin >> str;
for(int i = 0; i < m; ++i) {
p[m - i - 1] = str[i] == '*' ? 0 : (str[i] - 'a' + 1);
}
cin >> str;
for(int i = 0; i < n; ++i) {
t[i] = str[i] == '*' ? 0 : (str[i] - 'a' + 1);
}
get_rev();
for(int i = 0; i < bit; ++i) {
a[i] = p[i] * p[i] * p[i];
b[i] = t[i];
}
FFT(a, 1); FFT(b, 1);
for(int i = 0; i < bit; ++i) {
ans[i] += a[i] * b[i];
}
for(int i = 0; i < bit; ++i) {
a[i] = p[i];
b[i] = t[i] * t[i] * t[i];
}
FFT(a, 1); FFT(b, 1);
for(int i = 0; i < bit; ++i) {
ans[i] += a[i] * b[i];
}
for(int i = 0; i < bit; ++i) {
a[i] = p[i] * p[i];
b[i] = t[i] * t[i];
}
FFT(a, 1); FFT(b, 1);
for(int i = 0; i < bit; ++i) {
ans[i] -= a[i] * b[i] * Complex(2, 0);
}
FFT(ans, -1);
queue<int> q;
for(int i = m - 1; i < n; ++i) {
if((int)(ans[i].real() / bit + 0.5) == 0) q.push(i - m + 2);
}
cout << q.size() << endl;
while(q.size()) {
cout << q.front() << " ";
q.pop();
}
cout << endl;
return 0;
}
洛谷 P4173 残缺的字符串 (FFT)的更多相关文章
- 洛谷P4173 残缺的字符串(FFT)
传送门 话说为什么字符串会和卷积扯上关系呢……到底得脑洞大到什么程度才能想到这种东西啊……大佬太珂怕了…… 因为通配符的关系,自动机已经废了 那么换种方式考虑,如果两个字符串每一位对应的编码都相等,那 ...
- 洛谷 P4173 残缺的字符串
(不知道xjb KMP可不可以做的说) (假设下标都以0开头) 对于有一定偏移量的序列的 对应位置 匹配或者数值计算的题,这里是有一种套路的,就是把其中一个序列翻转过来,然后卷积一下,所得到的新序列C ...
- 洛谷P4173 残缺的字符串
题目大意: 两个带通配符的字符串\(a,b\),求\(a\)在\(b\)中出现的位置 字符串长度\(\le 300000\) 考虑魔改一发\(kmp\),发现魔改不出来 于是考虑上网搜题解 然后考虑\ ...
- 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,先考虑 ...
- luoguP4173 残缺的字符串 FFT
luoguP4173 残缺的字符串 FFT 链接 luogu 思路 和昨天做的题几乎一样. 匹配等价于(其实我更喜欢fft从0开始) \(\sum\limits_{i=0}^{m-1}(S[i+j]- ...
- BZOJ 4259: 残缺的字符串 [FFT]
4259: 残缺的字符串 题意:s,t,星号任意字符,匹配方案数 和上题一样 多乘上一个\(a_{j+i}\)就行了 #include <iostream> #include <cs ...
- 洛谷.3803.[模板]多项式乘法(FFT)
题目链接:洛谷.LOJ. FFT相关:快速傅里叶变换(FFT)详解.FFT总结.从多项式乘法到快速傅里叶变换. 5.4 又看了一遍,这个也不错. 2019.3.7 叕看了一遍,推荐这个. #inclu ...
随机推荐
- 微信支付(JsApi)
这两天有个小项目用的微信网页jsapi支付 用的thinkphp框架开发 ,首次做微信支付 碰了很多壁,做了简单就记录,方便回顾 也希望对大家能有点帮助,也希望路过的大神批评指正.. 一.必备条件及相 ...
- 阻抗匹配 及 SI9000 使用
1. 阻抗匹配 1. 波长 * 频率 = 光速(3*10^8) 2. PCB走线什么时候需要做阻抗匹配? 不主要看频率,而关键是看信号的边沿陡峭程度,即信号的上升/下降时间,一般认为如果信号的上升/下 ...
- Python37不能启动pyspider
报错内容: Traceback (most recent call last): File "/usr/local/var/pyenv/versions/3.7.3/bin/pyspider ...
- CF1220F
CF1220F 把整棵树分成1的左边和1的右边两部分 最优情况两边子树深度的差一定可以是一 如果还可以是2,也可以通过把多的那一边的点往另一边移使他变成1 如果往一个端点加点,一定不会使这一边变优,也 ...
- Python菜鸟之传参
Python菜鸟之传参 : 看上面enroll( )函数的调用传参 enroll("twiggy","M",city="上海", age=2 ...
- 关于JDK,tomcat,eclipse的配置
1.下载安装JDK 在自定义安装路径时,jdk和之后的jre文件夹是属于平行结构,我的安装路径为:D:\jdk\jdk1.6.0_43和D:\jdk\jre6 然后是对环境变量的配置, 计算机→属性→ ...
- Stm32CubeMX5 配置 外部中断
实验使用连接PA8引脚的按键触发中断,外部中断使用双边沿触发,这样就可以检测按键按下与松开,当按键按下时点亮LED, 当按键松开是关闭LED,在中断服务函数中只置位相应的标志,在main函数中具体处理 ...
- Linux环境安装Nginx步骤
centos7平台编译环境使用如下指令安装: 1. 安装make: yum -y install gcc automake autoconf libtool make 2. 安装g++: yum -y ...
- 统计List中相同的元素
public static <E> List<E> getCommonsElements(List<E> list) { return list.stream() ...
- linux网络配置 转
1.常用配置网络指令 (1) 配置eth0的IP地址, 同时激活该设备 1 sudo ifconfig eth0 192.168.1.10 netmask 255.255.255.0 up (2) 添 ...