洛谷P4173 残缺的字符串
题目大意:
两个带通配符的字符串\(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 残缺的字符串的更多相关文章
- 洛谷 P4173 残缺的字符串 (FFT)
题目链接:P4173 残缺的字符串 题意 给定长度为 \(m\) 的模式串和长度为 \(n\) 的目标串,两个串都带有通配符,求所有匹配的位置. 思路 FFT 带有通配符的字符串匹配问题. 设模式串为 ...
- 洛谷P4173 残缺的字符串(FFT)
传送门 话说为什么字符串会和卷积扯上关系呢……到底得脑洞大到什么程度才能想到这种东西啊……大佬太珂怕了…… 因为通配符的关系,自动机已经废了 那么换种方式考虑,如果两个字符串每一位对应的编码都相等,那 ...
- 洛谷 P4173 残缺的字符串
(不知道xjb KMP可不可以做的说) (假设下标都以0开头) 对于有一定偏移量的序列的 对应位置 匹配或者数值计算的题,这里是有一种套路的,就是把其中一个序列翻转过来,然后卷积一下,所得到的新序列C ...
- Luogu P4173 残缺的字符串-FFT在字符串匹配中的应用
P4173 残缺的字符串 FFT在字符串匹配中的应用. 能解决大概这种问题: 给定长度为\(m\)的A串,长度为\(n\)的B串.问A串在B串中的匹配数 我们设一个函数(下标从\(0\)开始) \(C ...
- P4173 残缺的字符串(FFT字符串匹配)
P4173 残缺的字符串(FFT字符串匹配) P4173 解题思路: 经典套路将模式串翻转,将*设为0,设以目标串的x位置匹配结束的匹配函数为\(P(x)=\sum^{m-1}_{i=0}[A(m-1 ...
- BZOJ1856或洛谷1641 [SCOI2010]生成字符串
BZOJ原题链接 洛谷原题链接 可以将\(1\)和\(0\)的个数和看成是\(x\)轴坐标,个数差看成\(y\)轴坐标. 向右上角走,即\(x\)轴坐标\(+1\),\(y\)轴坐标\(+1\),表示 ...
- 卡特兰数 洛谷P1641 [SCOI2010]生成字符串
卡特兰数 参考博客 介绍 卡特兰数为组合数学中的一种特殊数列,用于解决一类特殊问题 设\(f(n)\)为卡特兰数的第n项 其通项公式为 \[f(n)=\frac{2n\choose n}{n+1} \ ...
- 洛谷 P1641 [SCOI2010]生成字符串
洛谷 这题一看就是卡塔兰数. 因为\(cnt[1] \leq cnt[0]\),很显然的卡塔兰嘛! 平时我们推导卡塔兰是用一个边长为n的正方形推的, 相当于从(0,0)点走到(n,n)点,向上走的步数 ...
- 洛谷P1852 奇怪的字符串
题目描述 输入两个01串,输出它们的最长公共子序列的长度 输入输出格式 输入格式: 一行,两个01串 输出格式: 最长公共子序列的长度 输入输出样例 输入样例#1: 复制 01010101010 00 ...
随机推荐
- P4287 [SHOI2011]双倍回文
题意 考虑对每个节点\(x\)维护\(lastpos_x\)表示\(x\)的所有后缀回文串中第一个\(len\leqslant len_x/2\)并且能和\(x\)最后一个字符匹配的,之后枚举节点,判 ...
- SQL Server内部如何管理对象的数据Page?
一个表或Index使用的数据页空间是由IAM Page Chain来管理的.SQL Server 使用一个IAM(Index Allocation Map)Page来管理数据库文件中最多4GB的空间, ...
- 最全的.NET Core跨平台微服务学习资源
一.Asp.net Core基础 微软中文官网:https://docs.microsoft.com/zh-cn/aspnet/core/getting-started/ 微软英文官网:https:/ ...
- IIS安装和ASP.NET Web应用程序开发期间部署到IIS自定义主机域名并附加进程调试
一.IIS安装,此处以Windows10操作系统为例 首先依次进入控制面板=>程序=>程序与功能=>启用或关闭Windows功能 将Internet开头的三个选项全部打钩后点击确定安 ...
- Z从壹开始前后端分离【 .NET Core2.2/3.0 +Vue2.0 】框架之六 || API项目整体搭建 6.1 仓储+服务+抽象接口模式
本文梯子 本文3.0版本文章 前言 零.完成图中的粉色部分 2019-08-30:关于仓储的相关话题 一.创建实体Model数据层 二.设计仓储接口与其实现类 三.设计服务接口与其实现类 四.创建 C ...
- RandomAccessFile(),读写文件数据的API,以及复制文件操作
package seday03;import java.io.File;import java.io.RandomAccessFile; import java.io.IOException; /** ...
- Zipkin架构简介
Zipkin基本概念 Span:基本工作单元,一次链路调用就会创建一个Span Trace:一组Span的集合,表示一条调用链路.举个例子:当前存在服务A调用服务B然后调用服务C,这个A->B- ...
- rsync 未授权访问漏洞
rsync rsync,remote synchronize顾名思意就知道它是一款实现远程同步功能的软件,它在同步文件的同时,可以保持原来文件的权限.时间.软硬链接等附加信息. rsync是用 &qu ...
- Android 布局测试
wrap_content <Button android:id="@+id/button1" android:layout_width="wrap_content& ...
- Android SDK自带调试优化工具
Android sdk中自带了一些分析内存,界面调优的非常实用的工具,这对于分析和调试我们的应用十分有帮助,由于我使用的是linux版本的sdk,所以就以linux版本的工具做一个介绍,这些工具的具体 ...