题目

有一个长度为 \(m\) 的字符串 \(A\) 和 一个长度为 \(n\) 的字符串 \(B\),

它们有若干位置为通配符,现在问 \(B\) 的每一个后缀是否存在前缀为 \(A\)。


分析

考虑每次就是问 \(A[m-i]\) 与 \(B[r-i+1]\) 是否相等,把 \(A\) 反转一下,就得到 \(A'[i]\)

然后建立一个匹配函数 \((A[i]-B[j])^2A[i]B[j]\) 一定要乘起来之后都为0,这个后缀才有可能。

然后NTT好像会被卡,所以写了FFT


代码

#include <cstdio>
#include <cctype>
#include <cmath>
#include <cstring>
#include <algorithm>
#define rr register
#define mem(f,n) fill(f,f+n,(CP){0,0})
#define cpy(f,g,n) memcpy(f,g,sizeof(CP)*(n))
using namespace std;
const double pi=acos(-1.0);
const int N=2000011; int n,m,len,a[N],b[N],stac[N],TOP;
double Sin[31],Cos[31];
struct CP{
double x,y;
inline CP operator +(const CP &t)const{return (CP){x+t.x,y+t.y};}
inline CP operator -(const CP &t)const{return (CP){x-t.x,y-t.y};}
inline CP operator *(const CP &t)const{return (CP){x*t.x-y*t.y,x*t.y+y*t.x};}
}ff[N<<2],ans[N<<2];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
namespace Fourier{
int rev[N<<2],LAST; CP Wt[N<<2],F[N<<2];
inline void Pro(int n){
if (LAST==n) return; LAST=n,Wt[0]=(CP){1,0};
for (rr int i=0;i<n;++i)
rev[i]=(rev[i>>1]>>1)|((i&1)?n>>1:0);
}
inline void FFT(CP *f,int n,int op){
Pro(n);
for (rr int i=0;i<n;++i) F[i]=f[rev[i]];
for (rr int o=1,len=1;len<n;++o,len<<=1){
rr CP W=(CP){Cos[o-1],(op==1)?Sin[o-1]:-Sin[o-1]};
for (rr int j=1;j<len;++j) Wt[j]=Wt[j-1]*W;
for (rr int i=0;i<n;i+=len+len)
for (rr int j=0;j<len;++j){
rr CP t=Wt[j]*F[i|j|len];
F[i|j|len]=F[i|j]-t,F[i|j]=F[i|j]+t;
}
}
for (rr int i=0;i<n;++i) f[i]=F[i];
}
inline void Cb(CP *f,CP *g,int n){
for (rr int i=0;i<n;++i) f[i]=f[i]*g[i];
}
}
inline void CosSin(){
for (rr int i=0;i<31;++i) Cos[i]=cos(pi/(1<<i));
for (rr int i=0;i<31;++i) Sin[i]=sin(pi/(1<<i));
}
signed main(){
m=iut(),n=iut(),CosSin();
for (rr int i=0;i<m;++i){
rr char ch=getchar();
while (!isalpha(ch)&&ch!='*') ch=getchar();
if (ch!='*') a[i]=ch-96;
}
for (rr int i=0;i<n;++i){
rr char ch=getchar();
while (!isalpha(ch)&&ch!='*') ch=getchar();
if (ch!='*') b[i]=ch-96;
}
reverse(a,a+m); for (len=1;len<n+n;len<<=1);
for (rr int i=0;i<len;++i) ff[i]=(CP){a[i]*a[i]*a[i]/676.0,b[i]*1.0};
Fourier::FFT(ff,len,1),Fourier::Cb(ff,ff,len);
for (rr int i=0;i<len;++i) ans[i].x+=ff[i].y/2;
for (rr int i=0;i<len;++i) ff[i]=(CP){a[i]*1.0,b[i]*b[i]*b[i]/676.0};
Fourier::FFT(ff,len,1),Fourier::Cb(ff,ff,len);
for (rr int i=0;i<len;++i) ans[i].x+=ff[i].y/2;
for (rr int i=0;i<len;++i) ff[i]=(CP){a[i]*a[i]/26.0,b[i]*b[i]/26.0};
Fourier::FFT(ff,len,1),Fourier::Cb(ff,ff,len);
for (rr int i=0;i<len;++i) ans[i].x-=ff[i].y;
Fourier::FFT(ans,len,-1);
for (rr int i=0;i<len;++i) ans[i].x=ans[i].x*676.0/len;
for (rr int i=m-1;i<n;++i) if (fabs(ans[i].x)<0.5) stac[++TOP]=i-m+2;
print(TOP);
for (rr int i=1;i<=TOP;++i)
putchar(i==1?10:32),print(stac[i]);
return 0;
}

#FFT#P4173 残缺的字符串的更多相关文章

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

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

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

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

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

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

  4. P4173 残缺的字符串 fft

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

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

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

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

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

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

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

  8. luogu P4173 残缺的字符串

    传送门 两种做法,一种是依次考虑每种字符,然后如果某个位置是该字符或者是\(*\)对应的值就是1,否则是0,然后把第一个串倒过来,fft卷积起来,最后看对应位置的值是否为m 然而上面那个做法在字符集大 ...

  9. P4173 残缺的字符串

    题目链接 题意分析 啥 ? ? ? \(FFT\)做字符串匹配 可是就是这样 我们定义匹配函数 我们定义\(A\)是匹配串 \(B\)是被匹配串 我们当前到达\(B\)串的\(x\)位置 \[P(x) ...

  10. 洛谷 P4173 残缺的字符串

    (不知道xjb KMP可不可以做的说) (假设下标都以0开头) 对于有一定偏移量的序列的 对应位置 匹配或者数值计算的题,这里是有一种套路的,就是把其中一个序列翻转过来,然后卷积一下,所得到的新序列C ...

随机推荐

  1. 【Android逆向】破解看雪9月算法破解第三题

    这题的目标是算法还原,并写出注册机 1. 9月份算法第一题.apk 安装到手机 2. 随意输入账号密码,提示错误 3. apk拖入到jadx中 public native boolean regist ...

  2. 新零售SaaS架构:订单履约系统的应用架构梳理

    订单履约系统的核心能力 通过分析订单履约的全流程和各个业务活动,我们可以梳理出订单履约的核心业务链路,基于业务链路,我们抽象出订单履约系统的三大系统能力,分别为履约服务表达.履约调度.物流配送. 履约 ...

  3. sentinel的见解

    Sentinel 是面向分布式.多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量控制.熔断降级.热点流量防护等多个维度来帮助开发者保障微服务的稳定性.   在 Sentinel 里面,所 ...

  4. XAF Blazor FilterPanel 布局样式

    从上一篇关于ListView布局样式的文章中,我们知道XAFBlazor是移动优先的,如果想在PC端有更好的用户体验,我们需要对布局样式进行修改.这篇介绍在之前文章中提到的FilterPanel,它的 ...

  5. Nfs 共享存储搭建

    Nfs 共享存储搭建 为了实现不同操作系统中的数据共享,我们一般会搭建一些用于文件共享的服务器,nfs服务器就是其中一种,它实现的是linux与linux之间的共享.今天我将把如何在linux系统搭建 ...

  6. Failed to execute goal on project WebBackend: Could not resolve dependencies for project com.lang.yi:WebBackend:jar:1.0.0

    一.问题由来 自己在搭建项目的时候报一个错误,如标题所示,具体错误信息如下: Failed to execute goal on project WebBackend: Could not resol ...

  7. 真实开发中-redis在项目中的应用场景

    一.需求描述 从自己当前负责参与开发的一个项目中来看,redis主要的应用场景有如下几个,第一个是保存用户信息,这个需要频繁的获取.比如 在打开某一个页面进行查询时,就先需要获取用户信息,看用户是否具 ...

  8. 英语自定义标签 <i:juzi><i:zhuyu>John Smith</i:zhuyu></i:juzi> 主语谓语宾语

    效果 John Smith died in World War Two. John Smith killed three enemy soldiers. <style> i\:juzi { ...

  9. leaflet 领图 一个本地的类似百度地图工具-不连外网

    官网:https://leafletjs.com/ 二次开发手册-中文:http://112.91.146.167:9090/api/ 领图(一款给力的开源离线地图解决方案) https://blog ...

  10. KTL 最新支持Qt5窗口编程,一个支持C++14编辑公式的K线技术工具平台

    K,K线,Candle蜡烛图. T,技术分析,工具平台 L,公式Language语言使用c++14,Lite小巧简易. 项目仓库:https://github.com/bbqz007/KTL 国内仓库 ...