题目大意:

两个带通配符的字符串\(a,b\),求\(a\)在\(b\)中出现的位置

字符串长度\(\le 300000\)

考虑魔改一发\(kmp\),发现魔改不出来

于是考虑上网搜题解

然后考虑\(ntt\),发现两个串匹配需要满足\(\sum\limits_{i=0}^{n-1}(a_i-b_i)=0\)

发现不太对,可能有正有负相消等于\(0\),我们加上平方\(\sum\limits_{i=0}^{n-1}(a_i-b_i)^2=0\)

再考虑通配符,我们可以设通配符的价值为\(0\),然后变形一下\(\sum\limits_{i=0}^{n-1}a_i*b_i*(a_i-b_i)^2=0\)

展开得到\(\sum\limits_{i=0}^{n-1}a_i^3*b_i-2a_i^2*b_i^2+a_i*b_i^3\)

我们可以把这三项分开考虑

对于其中一项\(\sum\limits_{i=0}^{n-1}a_i^3*b_i\)

设\(a^{'}\)为\(a\)翻转,\(j=n-i-1\),答案为\(\sum\limits_{i=0}^{n-1}a_j^{'3}*b_i\)

然后卷起来,判断卷完之后\(i=(m-1\sim n-1)\)哪个系数是零,把\(i-m+2\)加入答案

#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
inline int read()
{
int x=0;char ch,f=1;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-') f=0,ch=getchar();
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?x:-x;
}
const int N=3e5+10,p=998244353,g=3,gi=332748118;
int n,m,limit,len;
char a[N],b[N];
int pos[N<<2];
int ret[N],num;
int a1[N<<2],b1[N<<2],c[N<<2];
inline int fast(int x,int k)
{
int ret=1;
while(k)
{
if(k&1) ret=ret*x%p;
x=x*x%p;
k>>=1;
}
return ret;
}
inline void ntt(int *a,int inv)
{
for(int i=0;i<limit;++i)
if(i<pos[i]) swap(a[i],a[pos[i]]);
for(int mid=1;mid<limit;mid<<=1)
{
int Wn=fast(inv?g:gi,(p-1)/(mid<<1));
for(int r=mid<<1,j=0;j<limit;j+=r)
{
int w=1;
for(int k=0;k<mid;++k,w=w*Wn%p)
{
int x=a[j+k],y=w*a[j+k+mid]%p;
a[j+k]=(x+y)%p;
a[j+k+mid]=(x-y)%p;
if(a[j+k+mid]<0) a[j+k+mid]+=p;
}
}
}
if(inv) return;
inv=fast(limit,p-2);
for(int i=0;i<limit;++i) a[i]=a[i]*inv%p;
}
inline void work(int *a,int *b,int opt)
{
ntt(a,1);ntt(b,1);
for(int i=0;i<limit;++i) c[i]=c[i]+a[i]*b[i]*opt;
}
inline void main()
{
m=read(),n=read();
scanf("%s%s",a,b);
for(int i=0;i<m;++i)
{
if(a[i]=='*') a[i]=0;
else a[i]=a[i]-'a'+1;
}
for(int i=0;i<n;++i)
{
if(b[i]=='*') b[i]=0;
else b[i]=b[i]-'a'+1;
}
reverse(a,a+m);
for(limit=1;limit<=n+m;limit<<=1) ++len;
for(int i=0;i<limit;++i) pos[i]=(pos[i>>1]>>1)|((i&1)<<(len-1));
for(int i=0;i<m;++i) a1[i]=a[i]*a[i]*a[i];
for(int i=0;i<n;++i) b1[i]=b[i];
work(a1,b1,1);
for(int i=0;i<limit;++i) a1[i]=b1[i]=0;
for(int i=0;i<m;++i) a1[i]=a[i]*a[i];
for(int i=0;i<n;++i) b1[i]=b[i]*b[i];
work(a1,b1,-2);
for(int i=0;i<limit;++i) a1[i]=b1[i]=0;
for(int i=0;i<m;++i) a1[i]=a[i];
for(int i=0;i<n;++i) b1[i]=b[i]*b[i]*b[i];
work(a1,b1,1);
ntt(c,0);
for(int i=m-1;i<n;++i)
{
if(!c[i]) ret[++num]=i-m+2;
}
printf("%lld\n",num);
for(int i=1;i<=num;++i) printf("%lld ",ret[i]);
}
}
signed main()
{
red::main();
return 0;
}

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

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

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

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

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

  3. 洛谷 P4173 残缺的字符串

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

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

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

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

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

  6. BZOJ1856或洛谷1641 [SCOI2010]生成字符串

    BZOJ原题链接 洛谷原题链接 可以将\(1\)和\(0\)的个数和看成是\(x\)轴坐标,个数差看成\(y\)轴坐标. 向右上角走,即\(x\)轴坐标\(+1\),\(y\)轴坐标\(+1\),表示 ...

  7. 卡特兰数 洛谷P1641 [SCOI2010]生成字符串

    卡特兰数 参考博客 介绍 卡特兰数为组合数学中的一种特殊数列,用于解决一类特殊问题 设\(f(n)\)为卡特兰数的第n项 其通项公式为 \[f(n)=\frac{2n\choose n}{n+1} \ ...

  8. 洛谷 P1641 [SCOI2010]生成字符串

    洛谷 这题一看就是卡塔兰数. 因为\(cnt[1] \leq cnt[0]\),很显然的卡塔兰嘛! 平时我们推导卡塔兰是用一个边长为n的正方形推的, 相当于从(0,0)点走到(n,n)点,向上走的步数 ...

  9. 洛谷P1852 奇怪的字符串

    题目描述 输入两个01串,输出它们的最长公共子序列的长度 输入输出格式 输入格式: 一行,两个01串 输出格式: 最长公共子序列的长度 输入输出样例 输入样例#1: 复制 01010101010 00 ...

随机推荐

  1. You Are Given a Decimal String... CodeForces - 1202B [简单dp][补题]

    补一下codeforces前天教育场的题.当时只A了一道题. 大致题意: 定义一个x - y - counter :是一个加法计数器.初始值为0,之后可以任意选择+x或者+y而我们由每次累加结果的最后 ...

  2. Noip刷题计划

    写在前面 去年也想刷10年NOIP来着..结果刷到13年就没动力了233... 今年一定要完成目标啊!! "愿你明日重生,醒时心存冬阳" 2018年 题目 首次得分 出错原因 考点 ...

  3. Eclipse Memory Analyzer(MAT),内存泄漏插件,安装使用一条龙

    网上文档很多,但最初都有问题.整理一份,作为备份.使用过程:开发代码写完后,对可能出现内存溢出的代码,添加配置文件,生成.hprof文件,用memory Analyzer分析排查问题,且泄漏内存大小可 ...

  4. vue动画实现方式

    vue动画实现方式 <!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset=&q ...

  5. Java设计模式:Abstract Factory(抽象工厂)模式

    概念定义 抽象工厂(Abstract Factory)模式提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. 抽象工厂模式中,系统的产品有多于一个的产品族(一个产品族里定义多个产品) ...

  6. svn版本管理配置权限

    修改svn配置 编辑svnserve.conf文件 第19,20行删掉前面的#--意思就是打开 ancon-access = none  匿名用户不可读 auth-access = write 认证可 ...

  7. bootstrap 自定义模态窗口

    $(".classname").click(function () { $('#mymodel').modal('show'); alert('模态框打开了'); }); $('# ...

  8. java高并发系列 - 第13天:JUC中的Condition对象

    本文目标: synchronized中实现线程等待和唤醒 Condition简介及常用方法介绍及相关示例 使用Condition实现生产者消费者 使用Condition实现同步阻塞队列 Object对 ...

  9. 接口的 COM 组件调用 QueryInterface 因以下错误而失败: 库没有注册。

    这个问题原因是因为安装了高版本的office然后卸载掉,又安装了低版本的office导致的. 博主是 office2016卸载后,安装了office2013. EXCEL报错信息为: 无法将类型为“M ...

  10. javafx笔记----非javafx线程Platform.runLater赋值不生效情况

    Platform.runLater(() -> { // }); Platform.runLater一些情况下没有赋值到fx页面上 采用task方式 Task<SB> task = ...