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字符串匹配)的更多相关文章

  1. BZOJ4259: 残缺的字符串(FFT 字符串匹配)

    题意 题目链接 Sol 知道FFT能做字符串匹配的话这就是个裸题了吧.. 考虑把B翻转过来,如果\(\sum_{k = 0}^M (B_{i - k} - A_k)^2 * B_{i-k}*A_k = ...

  2. Luogu P4173 残缺的字符串-FFT在字符串匹配中的应用

    P4173 残缺的字符串 FFT在字符串匹配中的应用. 能解决大概这种问题: 给定长度为\(m\)的A串,长度为\(n\)的B串.问A串在B串中的匹配数 我们设一个函数(下标从\(0\)开始) \(C ...

  3. 洛谷 P4173 残缺的字符串 (FFT)

    题目链接:P4173 残缺的字符串 题意 给定长度为 \(m\) 的模式串和长度为 \(n\) 的目标串,两个串都带有通配符,求所有匹配的位置. 思路 FFT 带有通配符的字符串匹配问题. 设模式串为 ...

  4. P4173 残缺的字符串 fft

    题意:给你两个字符串,问你第一个在第二个中出现过多少次,并输出位置,匹配时是模糊匹配*可和任意一个字符匹配 题解:fft加速字符串匹配; 假设上面的串是s,s长度为m,下面的串是p,p长度为n,先考虑 ...

  5. luoguP4173 残缺的字符串 FFT

    luoguP4173 残缺的字符串 FFT 链接 luogu 思路 和昨天做的题几乎一样. 匹配等价于(其实我更喜欢fft从0开始) \(\sum\limits_{i=0}^{m-1}(S[i+j]- ...

  6. BZOJ4259:残缺的字符串(FFT)

    Description 很久很久以前,在你刚刚学习字符串匹配的时候,有两个仅包含小写字母的字符串A和B,其中A串长度为m,B串长度为n.可当你现在再次碰到这两个串时,这两个串已经老化了,每个串都有不同 ...

  7. 【BZOJ4259】残缺的字符串 FFT

    [BZOJ4259]残缺的字符串 Description 很久很久以前,在你刚刚学习字符串匹配的时候,有两个仅包含小写字母的字符串A和B,其中A串长度为m,B串长度为n.可当你现在再次碰到这两个串时, ...

  8. BZOJ 4259: 残缺的字符串 [FFT]

    4259: 残缺的字符串 题意:s,t,星号任意字符,匹配方案数 和上题一样 多乘上一个\(a_{j+i}\)就行了 #include <iostream> #include <cs ...

  9. FFT字符串匹配

    本文半原创 参考资料:其实就是照抄的什么参考啊 我们知道KMP可以用来在线性复杂度内进行制胡窜匹配 今天教您一种新方法:用FFT进行字符串匹配 您可能觉得这很玄学,FFT不是做多项式卷积的吗,怎么还可 ...

随机推荐

  1. Python反射笔记

    通过字符串的形式,导入模块.使用__import__ In [3]: SYS = __import__("sys") In [4]: SYS.path 如果导入模块在多级文件夹下 ...

  2. Redis安装(单机及各类集群,阿里云)

    Redis安装(单机及各类集群,阿里云) 前言 上周,我朋友突然悄悄咪咪地指着手机上的一篇博客说,这是你的博客吧.我看了一眼,是之前发布的<Rabbit安装(单机及集群,阿里云>.我朋友很 ...

  3. 深入Synchronized的实现原理与源码分析

    前言 一.synchronized的特性 1.1 原子性 1.2 可见性 1.3 有序性 1.4 可重入性 二.synchronized的用法 三.synchronized锁的实现 3.1 同步方法 ...

  4. flask迁移数据库时报错:Target database is not up的解决方案

    在flask中进行数据库迁移时报错,报错信息为"Target database is not up",解决方案如下 找到alembic的最新版本号,找到文件夹migrate下的最新 ...

  5. elasticsearch定时删除索引第二版

    该版本对于上一个版本做了升级.兼容性更好了. #!/bin/bash ####################################################### # $Name: ...

  6. 大数据-HDFS 集群搭建的配置文件

    1.HDFS简单版集群搭建相关配置文件 1.core-site.xml文件 <property> <name>fs.defaultFS</name> <val ...

  7. openjudge 7622 求排列的逆序数(归并)

    7622:求排列的逆序数 总时间限制:  1000ms   内存限制:  65536kB 描述 在Internet上的搜索引擎经常需要对信息进行比较,比如可以通过某个人对一些事物的排名来估计他(或她) ...

  8. Go 每日一库之 flag

    缘起 我一直在想,有什么方式可以让人比较轻易地保持每日学习,持续输出的状态.写博客是一种方式,但不是每天都有想写的,值得写的东西. 有时候一个技术比较复杂,写博客的时候经常会写着写着发现自己的理解有偏 ...

  9. Java 用集合实现简单的斗地主发牌

    创建数组.集合,存放数据 public class FightAgainstLandlords { /** * poker集合,存储54张牌 */ private ArrayList<Strin ...

  10. C++Primer第五版 3.5.1节练习

    练习 3.27:假设txt_size是一个无参数的函数,它的返回值是int.请回答下列哪个定义是非法的?为什么? Unsigned buf_size = 1024; (a) int ia[buf_si ...