正题

题目链接:https://www.luogu.com.cn/problem/P4173


题目大意

给出两个字符串\(S,T\),其中包含小写字母和一些\(?\),\(?\)可以匹配任何字符。

求有多少个\(p\)使得\(T_{0\sim |t|-1}=S_{p\sim p+|t|-1}\)


解题思路

如果不考虑\(?\),我们可以用做差法来匹配两个字符,构造匹配函数

\[f(x)=\sum_{i=0}^{m}(T_i-S_{x+i})^2
\]

这样若\(f(x)=0\)证明它们在位置\(x\)处匹配。

但是现在有\(?\),也就是要跳过有\(?\)的位置,定义\(?\)的值为\(0\),然后改一下匹配函数

\[f(x)=\sum_{i=0}^{m}(T_i-S_{x+i})^2T_iS_{x+i}
\]

展开二次项

\[f(x)=\sum_{i=0}^{m}T_i^3S_{x+i}-2T_{i}^2S_{x+i}^2+T_iS_{x+i}^3
\]

把\(T\)反过来就是\(\sum_{i=0}^{m}T_{m-i-1}^3S_{x+i}-2T_{m-i-1}^2S_{x+i}^2+T_{m-i-1}S_{x+i}^3\)

然后有三个式子卷积之后加起来就好了。

常数极大,开\(\text{-O2}\)才能过。时间复杂度\(O(n\log n)\)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define int long long
using namespace std;
const int N=1e6+2e5;
const double Pi=acos(-1);
struct complex{
double x,y;
complex(double xx=0,double yy=0)
{x=xx;y=yy;return;}
};
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);}
struct poly{
complex a[N];
}F[3],G[3];
int n,m,r[N],k;
char s[N],t[N];
queue<int> q;
void FFT(complex *f,int op,int n){
for(int i=0;i<n;i++)
if(i<r[i])swap(f[i],f[r[i]]);
for(int p=2;p<=n;p<<=1){
int len=p>>1;
complex tmp(cos(Pi/len),sin(Pi/len)*op);
for(int k=0;k<n;k+=p){
complex buf(1,0);
for(int i=k;i<k+len;i++){
complex tt=buf*f[i+len];
f[i+len]=f[i]-tt;
f[i]=f[i]+tt;
buf=buf*tmp;
}
}
}
if(op==-1)
for(int i=0;i<n;i++)
f[i].x/=(double)n;
return;
}
void mul(poly &a,poly &b){
FFT(a.a,1,k);FFT(b.a,1,k);
for(int i=0;i<k;i++)
a.a[i]=a.a[i]*b.a[i];
FFT(a.a,-1,k);
return;
}
signed main()
{
scanf("%d%d",&m,&n);
scanf("%s",t);scanf("%s",s);
for(int i=0;i<n;i++){
char c=s[i];int z=s[i]-'a'+1;
if(c=='*')z=0;
F[0].a[i]=complex(z*z*z,0);
F[1].a[i]=complex(z*z,0);
F[2].a[i]=complex(z,0);
}
for(int i=0;i<m;i++){
char c=t[m-i-1];int z=c-'a'+1;
if(c=='*')z=0;
G[0].a[i]=complex(z,0);
G[1].a[i]=complex(z*z,0);
G[2].a[i]=complex(z*z*z,0);
}
k=1;for(k=1;k<=2*n;)k<<=1;
for(int i=0;i<k;i++)
r[i]=(r[i>>1]>>1)|((i&1)?(k>>1):0);
mul(F[0],G[0]);mul(F[1],G[1]);mul(F[2],G[2]);
for(int i=0;i<k;i++)
F[0].a[i].x=F[0].a[i].x-2.0*F[1].a[i].x+F[2].a[i].x;
k=0;
for(int i=0;i<=n-m;i++)
if(fabs(F[0].a[i+m-1].x)<0.5)
k++,q.push(i);
printf("%d\n",k);
while(!q.empty())
printf("%d ",q.front()+1),q.pop();
return 0;
}

P4173-残缺的字符串【FFT】的更多相关文章

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

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

  2. P4173 残缺的字符串(FFT字符串匹配)

    P4173 残缺的字符串(FFT字符串匹配) P4173 解题思路: 经典套路将模式串翻转,将*设为0,设以目标串的x位置匹配结束的匹配函数为\(P(x)=\sum^{m-1}_{i=0}[A(m-1 ...

  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. BZOJ 4259: 残缺的字符串 [FFT]

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

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

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

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

    传送门 话说为什么字符串会和卷积扯上关系呢……到底得脑洞大到什么程度才能想到这种东西啊……大佬太珂怕了…… 因为通配符的关系,自动机已经废了 那么换种方式考虑,如果两个字符串每一位对应的编码都相等,那 ...

  9. [Luogu P4173]残缺的字符串 ( 数论 FFT)

    题面 传送门:洛咕 Solution 这题我写得脑壳疼,我好菜啊 好吧,我们来说正题. 这题.....emmmmmmm 显然KMP类的字符串神仙算法在这里没法用了. 那咋搞啊(或者说这题和数学有半毛钱 ...

  10. P4173 残缺的字符串(FFT)

    [Luogu4173] 题解 \(1.\)定义匹配函数 \(2.\)定义完全匹配函数 \(3.\)快速计算每一位的完全匹配函数值 #include<cstdio> #include< ...

随机推荐

  1. flutter查看安全码SHA1

    最近flutter技术调研高德地图插件时,要用到安全码,可以打开cmd,键入一下命令查看.(注意路径用户名yourusernamehere改为自己的) keytool -list -v -keysto ...

  2. [转]C# 互操作性入门系列(三):平台调用中的数据封送处理

    参考网址:https://www.cnblogs.com/FongLuo/p/4512738.html C#互操作系列文章: C# 互操作性入门系列(一):C#中互操作性介绍 C# 互操作性入门系列( ...

  3. 把 nodejs koa2 制作的后台接口 部署到 腾讯云服务器

    我 使用 nodejs koa2框架 制作后端接口, 现在将nodejs koa2 部署到服务器 koa2项目 实现 接口 可以看我的 这篇文章: 简单实现 nodejs koa2 mysql 增删改 ...

  4. ASP.NET Core教程:ASP.NET Core程序部署到Linux

    一.前言 这篇文章我们将讲解如何将ASP.NET Core 程序部署到Linux.这里我们使用的是虚拟机里面安装的Centos7.这里的ASP.NET Core程序,以上篇文章中发布的框架依赖文件为例 ...

  5. asp.net core 知识点总结

  6. Redis3.0.0集群一键脚本 -by古斌

    下载地址(以交由码云托管): https://gitee.com/gubin0412/Redis3.0.0 赋予脚本执行权限  chmod +x redis-gubin.sh 使用 ./redis-g ...

  7. 回忆java输入输出流,走出误区

    input read 将一个XXX读入(input)---从输入流中读取数据的下一个字节(code操作的).output write 将一个类型的数据写入此流(code操作的)---然后把XXX输出( ...

  8. Flink的状态管理与恢复机制

    参考地址:https://www.cnblogs.com/airnew/p/9544683.html 问题一.什么是状态? 问题二.Flink状态类型有哪几种? 问题三.状态有什么作用? 问题四.如何 ...

  9. IDEA常用设置及推荐插件

    IDEA常用设置及推荐插件 本文主要记录IDEA的一些常用设置,IDEA与Eclipse的常用快捷键对比及推荐一些好用的插件. 基本设置 设置界面风格及修改外部UI尺寸大小 打开IDEA时设置不重新打 ...

  10. MySQL-Cluster 初识

          最近,对mysql-cluster进行初步了解,发现和oracle提供的RAC有一定的相似之处,但区别又很大,下面主要是mysql-cluster的搭建,至于对其的深入了解,留着以后工作需 ...