P4173 残缺的字符串(FFT字符串匹配)
P4173 残缺的字符串(FFT字符串匹配)
P4173
解题思路:
经典套路将模式串翻转,将*设为0,设以目标串的x位置匹配结束的匹配函数为\(P(x)=\sum^{m-1}_{i=0}[A(m-1-i)-B(x-(m-1-i))]^2A(m-1-i)B(x-(m-1-i))]\),展开之后化简为\(P(x)=\sum_{i+j=x}A^3(i)B(j)-2\sum_{i+j=x}A^2(i)B^2(j)+\sum_{i+j=x}A(i)B^3(j)\)
做三次FFT即可,然后交题就出了一堆玄学错误
#include <bits/stdc++.h>
using namespace std;
/* freopen("k.in", "r", stdin);
freopen("k.out", "w", stdout); */
//clock_t c1 = clock();
//std::cerr << "Time:" << clock() - c1 <<"ms" << std::endl;
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#define de(a) cout << #a << " = " << a << endl
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define per(i, a, n) for (int i = n; i >= a; i--)
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef vector<int, int> VII;
#define inf 0x3f3f3f3f
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll MAXN = 2e6 + 10;
const ll MAXM = 5e6 + 7;
const ll MOD = 1e9 + 7;
const double eps = 1e-6;
const double pi = acos(-1.0);
struct Complex
{
double x, y;
Complex(double xx = 0, double yy = 0) { x = xx, y = yy; }
} a[MAXN], b[MAXN], c[MAXN];
Complex operator+(Complex a, Complex b) { return Complex(a.x + b.x, a.y + b.y); }
Complex operator-(Complex a, Complex b) { return Complex(a.x - b.x, a.y - b.y); }
Complex operator*(Complex a, Complex b) { return Complex(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x); } //不懂的看复数的运算那部分
int l = 0, r[MAXN];
int limit = 1;
void FFT(Complex *A, int type)
{
for (int i = 0; i < limit; i++)
if (i < r[i])
swap(A[i], A[r[i]]); //求出要迭代的序列
for (int mid = 1; mid < limit; mid <<= 1)
{ //待合并区间的长度的一半
Complex Wn(cos(pi / mid), type * sin(pi / mid)); //单位根
for (int R = mid << 1, j = 0; j < limit; j += R)
{ //R是区间的长度,j表示前已经到哪个位置了
Complex w(1, 0); //幂
for (int k = 0; k < mid; k++, w = w * Wn)
{ //枚举左半部分
Complex x = A[j + k], y = w * A[j + mid + k]; //蝴蝶效应
A[j + k] = x + y;
A[j + mid + k] = x - y;
}
}
}
/* if (type == -1)
for (int i = 0; i < limit; i++)
a[i].x /= limit; */
}
char s[MAXN], t[MAXN];
int ta[MAXN] = {0}, tb[MAXN] = {0};
int ans[MAXN] = {0};
int main()
{
int n, m;
scanf("%d%d%s%s", &m, &n, t, s);
for (int i = 0; i < m; i++)
ta[m - i - 1] = t[i] == '*' ? 0 : (t[i] - 'a' + 1);
for (int i = 0; i < n; i++)
tb[i] = s[i] == '*' ? 0 : (s[i] - 'a' + 1);
while (limit <= m + n)
limit <<= 1, l++;
for (int i = 0; i < limit; i++)
r[i] = (r[i >> 1] >> 1) | ((i & 1) << (l - 1));
for (int i = 0; i < limit; i++)
{
a[i] = Complex(ta[i], 0);
b[i] = Complex(tb[i] * tb[i] * tb[i], 0);
}
FFT(a, 1), FFT(b, 1);
for (int i = 0; i < limit; i++)
c[i] = c[i] + a[i] * b[i];
for (int i = 0; i < limit; i++)
{
a[i] = Complex(ta[i] * ta[i], 0);
b[i] = Complex(tb[i] * tb[i], 0);
}
FFT(a, 1), FFT(b, 1);
for (int i = 0; i < limit; i++)
c[i] = c[i] - a[i] * b[i] * Complex(2.0, 0);
for (int i = 0; i < limit; i++)
{
a[i] = Complex(ta[i] * ta[i] * ta[i], 0);
b[i] = Complex(tb[i], 0);
}
FFT(a, 1), FFT(b, 1);
for (int i = 0; i < limit; i++)
c[i] = c[i] + a[i] * b[i];
FFT(c, -1);
int cnt = 0;
for (int i = m - 1; i < n; i++)
{
if (int(c[i].x / limit + 0.5) == 0)
ans[cnt++] = i - m + 2;
}
printf("%d\n", cnt);
for (int i = 0; i < cnt; i++)
printf("%d ", ans[i]);
printf("\n");
return 0;
}
P4173 残缺的字符串(FFT字符串匹配)的更多相关文章
- BZOJ4259: 残缺的字符串(FFT 字符串匹配)
题意 题目链接 Sol 知道FFT能做字符串匹配的话这就是个裸题了吧.. 考虑把B翻转过来,如果\(\sum_{k = 0}^M (B_{i - k} - A_k)^2 * B_{i-k}*A_k = ...
- Luogu P4173 残缺的字符串-FFT在字符串匹配中的应用
P4173 残缺的字符串 FFT在字符串匹配中的应用. 能解决大概这种问题: 给定长度为\(m\)的A串,长度为\(n\)的B串.问A串在B串中的匹配数 我们设一个函数(下标从\(0\)开始) \(C ...
- 洛谷 P4173 残缺的字符串 (FFT)
题目链接:P4173 残缺的字符串 题意 给定长度为 \(m\) 的模式串和长度为 \(n\) 的目标串,两个串都带有通配符,求所有匹配的位置. 思路 FFT 带有通配符的字符串匹配问题. 设模式串为 ...
- 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]- ...
- BZOJ4259:残缺的字符串(FFT)
Description 很久很久以前,在你刚刚学习字符串匹配的时候,有两个仅包含小写字母的字符串A和B,其中A串长度为m,B串长度为n.可当你现在再次碰到这两个串时,这两个串已经老化了,每个串都有不同 ...
- 【BZOJ4259】残缺的字符串 FFT
[BZOJ4259]残缺的字符串 Description 很久很久以前,在你刚刚学习字符串匹配的时候,有两个仅包含小写字母的字符串A和B,其中A串长度为m,B串长度为n.可当你现在再次碰到这两个串时, ...
- BZOJ 4259: 残缺的字符串 [FFT]
4259: 残缺的字符串 题意:s,t,星号任意字符,匹配方案数 和上题一样 多乘上一个\(a_{j+i}\)就行了 #include <iostream> #include <cs ...
- FFT字符串匹配
本文半原创 参考资料:其实就是照抄的什么参考啊 我们知道KMP可以用来在线性复杂度内进行制胡窜匹配 今天教您一种新方法:用FFT进行字符串匹配 您可能觉得这很玄学,FFT不是做多项式卷积的吗,怎么还可 ...
随机推荐
- WebGPU学习(十一):学习两个优化:“reuse render command buffer”和“dynamic uniform buffer offset”
大家好,本文介绍了"reuse render command buffer"和"dynamic uniform buffer offset"这两个优化,以及Ch ...
- Java面向对象程序设计第8章3-5
Java面向对象程序设计第8章3-5 3.String类型有什么特点? 一旦赋值,便不能更改其指向的字符对象 如果更改,则会指向一个新的字符对象 不能为null 4.String什么时候进行值比较,什 ...
- 001 Ceph简介
一.Ceph简介 Red Hat Ceph是一个分布式的数据对象存储,系统设计旨在性能.可靠性和可扩展性上能够提供优秀的存储服务.Ceph分布式存储能够在一个统一的系统中同时提供了对象.块.和文件存储 ...
- spring boot(三)Junit 测试controller
Junit测试Controller(MockMVC使用),传输@RequestBody数据解决办法 一.单元测试的目的 简单来说就是在我们增加或者改动一些代码以后对所有逻辑的一个检测,尤其是在我们后期 ...
- Python基础入门必备知识
1 标识符标识符是编程时使用的名字,用于给变量.函数.语句块等命名,Python 中标识符由字母.数字.下划线组成,不能以数字开头,区分大小写. 以下划线开头的标识符有特殊含义,单下划线开头的标识符, ...
- 1.2 UML带来了什么(学习笔记)
需求->需求分析->设计->开发 uml 编号 uml元素 对于语言理解 1 元模型 基本词汇 2 表示法或视图 语法 3 RUP 方法(统一软件开发过程) 方法 4 控制类 定语 ...
- Serverless 设计理念:从头创建品牌标识
本文首发于 Serverless 中文网,译者:Aceyclee.如需转载,请保留原作者和出处. 如何在开源技术社区中做设计?本文来自 Serverless 团队中首席设计的分享 -- 展现了设计过程 ...
- 【Java基础总结】总结
总想着把学习的过程全都记录下来 以便某一时刻回头的时候,还能看见走过的路 对于基础来说,即使不回头看,也知道这条路是什么样子的 记录不记录,都无所谓 况且我不是专业的记录者,不记录比记录好 实在想不起 ...
- 更加清晰的TFRecord格式数据生成及读取
TFRecords 格式数据文件处理流程 TFRecords 文件包含了 tf.train.Example 协议缓冲区(protocol buffer),协议缓冲区包含了特征 Features.Ten ...
- Java框架之Spring02-AOP-动态代理-AspectJ-JdbcTemplate-事务
AOP 动态代理 代理设计模式的原理:使用一个代理将原本对象包装起来,然后用该代理对象”取代”原始对象.任何对原始对象的调用都要通过代理.代理对象决定是否以及何时将方法调用转到原始对象上. 代理模式的 ...