传送门

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

然而上面那个做法在字符集大小过大的时候会GG,所以考虑一次性匹配,如果不考虑通配符\(*\),设(开头)位置i的匹配函数为\(f(i)=\sum_{j=1}^{m}(a_j-b_{i+m-j})^2\),\(f(i)=0\)说明i可以匹配

因为通配符可以匹配任何字符,也就是会让某组匹配一定是0,那么\(f(i)\)可以改成\(f(i)=\sum_{j=1}^{m}(a_j-b_{i+m-j})^2a_jb_{i+m-j}\),化简得到\(f(i)=\sum_{j=1}^{m}{a_j}^3b_{i+m-j}+a_j{b_{i+m-j}}^3-2{a_j}^2{b_{i+m-j}}^2\),然后三遍fft就好了

然后我ntt被fft吊着打qwq

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define LL long long
#define db double
#define il inline
#define re register using namespace std;
const int N=(1<<20)+10,mod=998244353;
il int rd()
{
int x=0,w=1;char ch=0;
while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
int rdr[N];
il int fpow(int a,int b){int an=1;while(b){if(b&1) an=1ll*an*a%mod;a=1ll*a*a%mod,b>>=1;} return an;}
void ntt(int *a,int n,bool op)
{
int l=0,x,y;
while((1<<l)<n) ++l;
for(int i=0;i<n;++i) rdr[i]=(rdr[i>>1]>>1)|((i&1)<<(l-1));
for(int i=0;i<n;++i) if(i<rdr[i]) swap(a[i],a[rdr[i]]);
for(int i=1;i<n;i<<=1)
{
int ww=fpow(op?3:332748118,(mod-1)/(i<<1));
for(int j=0;j<n;j+=i<<1)
for(int k=0,w=1;k<i;++k,w=1ll*w*ww%mod)
x=a[j+k],y=1ll*a[j+k+i]*w%mod,a[j+k]=(x+y)%mod,a[j+k+i]=(x-y+mod)%mod;
}
if(!op) for(int i=0,w=fpow(n,mod-2);i<n;++i) a[i]=1ll*a[i]*w%mod;
}
int n,m,hh[N],a[N],b[N],an[N],ta;
char cc[N],ss[N]; int main()
{
n=rd(),m=rd();
int l=1;
while(l<=n+m) l<<=1;
scanf("%s%s",cc,ss);
for(int i=0;i<n;++i)
{
int x=cc[n-i-1]=='*'?0:cc[n-i-1]-96;
a[i]=x*x*x;
}
for(int i=0;i<m;++i)
{
int x=ss[i]=='*'?0:ss[i]-96;
b[i]=x;
}
ntt(a,l,1),ntt(b,l,1);
for(int i=0;i<l;++i) a[i]=1ll*a[i]*b[i]%mod;
ntt(a,l,0);
for(int i=1;i<=m;++i) hh[i]=(hh[i]+a[n+i-2])%mod;
for(int i=0;i<l;++i) a[i]=b[i]=0;
for(int i=0;i<n;++i)
{
int x=cc[n-i-1]=='*'?0:cc[n-i-1]-96;
a[i]=x;
}
for(int i=0;i<m;++i)
{
int x=ss[i]=='*'?0:ss[i]-96;
b[i]=x*x*x;
}
ntt(a,l,1),ntt(b,l,1);
for(int i=0;i<l;++i) a[i]=1ll*a[i]*b[i]%mod;
ntt(a,l,0);
for(int i=1;i<=m;++i) hh[i]=(hh[i]+a[n+i-2])%mod;
for(int i=0;i<l;++i) a[i]=b[i]=0;
for(int i=0;i<n;++i)
{
int x=cc[n-i-1]=='*'?0:cc[n-i-1]-96;
a[i]=x*x;
}
for(int i=0;i<m;++i)
{
int x=ss[i]=='*'?0:ss[i]-96;
b[i]=x*x;
}
ntt(a,l,1),ntt(b,l,1);
for(int i=0;i<l;++i) a[i]=1ll*a[i]*b[i]%mod;
ntt(a,l,0);
for(int i=1;i<=m;++i) hh[i]=((hh[i]-a[n+i-2]-a[n+i-2])%mod+mod)%mod;
for(int i=0;i<l;++i) a[i]=b[i]=0;
for(int i=1;i<=m-n+1;++i)
if(!hh[i]) an[++ta]=i;
printf("%d\n",ta);
for(int i=1;i<=ta;++i) printf("%d ",an[i]);
return 0;
}

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

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

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

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

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

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

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

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

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

  5. P4173 残缺的字符串 fft

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

  6. 洛谷 P4173 残缺的字符串

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

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

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

  8. 洛谷P4173 残缺的字符串

    题目大意: 两个带通配符的字符串\(a,b\),求\(a\)在\(b\)中出现的位置 字符串长度\(\le 300000\) 考虑魔改一发\(kmp\),发现魔改不出来 于是考虑上网搜题解 然后考虑\ ...

  9. P4173 残缺的字符串

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

随机推荐

  1. Nginx宣布正式支持gRPC,附示例代码

    原创 2018-03-20 薛命灯 聊聊架构 作者|Owen Garrett编辑|薛命灯 NGINX 官方博客正式宣布 NGINX 支持原生的 gPRC,现在就可以从代码仓库拉取快照版本.该特性将会被 ...

  2. bzoj4036[HAOI2015]set 按位或

    Vfk的集合幂级数论文的例题….随机集合并为全集的期望集合数….这篇题解里的东西基本来自vfk的论文. 首先根据期望的线性性,我们把需要走第1步的概率(一定为1)加上需要走第2步的概率(等于走了第一步 ...

  3. 使用postman测试dubbo服务层的方法

    下面的项目用的是servlet3.0架构 接口(doubbo消费者项目和服务者项目共享的jar项目中): package serviceinvoke; import com.alibaba.dubbo ...

  4. 生产环境Linux常用命令【随时更新】

    1. 查询文件中的关键字并高亮显示[查询当前目录关键字为elasticsearch的日志文件] find ./ -name "my-elasticsearch.log" | xar ...

  5. 过滤富文本编辑器中的html元素和其他元素

    https://blog.csdn.net/fjssharpsword/article/details/53467079 1.应用场景:从一份html文件中或从String(是html内容)中提取纯文 ...

  6. CentOS 7.0下使用yum安装MySQL

    CentOS7默认数据库是mariadb,配置等用着不习惯,因此决定改成mysql,但是CentOS7的yum源中默认好像是没有mysql的.为了解决这个问题,我们要先下载mysql的repo源. 1 ...

  7. Java抽象类、接口整理

    抽象类 5.1抽象类产生(上标为A) 编写一个类时,会给该类定义一些方法,这些方法是用来描述功能和具体实现的方式,这些方法都有方法体 例如:一个图形类应该有周长的方法,但是不同的图形求周长方法不一样. ...

  8. 网速测试脚本speedtest_cli的安装与使用

    speedtest_cli的安装与使用 1.下载 wget https://raw.github.com/sivel/speedtest-cli/master/speedtest.py 图 1 2.授 ...

  9. 使用二进制安装包的方式单机部署MySQL8.0.13

    使用二进制安装包的方式单机部署MySQL8.0.13 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 关于MySQL的介绍我这里就不多做赘述了,如何下载MySQL详情请参考:MySQ ...

  10. Hadoop生态圈-使用FreeIPA安装Kerberos和LDAP

    Hadoop生态圈-使用FreeIPA安装Kerberos和LDAP 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 有些大数据平台只是简单地通过防火墙来解决他们的网络安全问题.十分 ...