[Luogu P4173]残缺的字符串 ( 数论 FFT)
题面
传送门:洛咕
Solution
这题我写得脑壳疼,我好菜啊
好吧,我们来说正题。
这题.....emmmmmmm
显然KMP类的字符串神仙算法在这里没法用了。
那咋搞啊(或者说这题和数学有半毛钱关系啊)
我们考虑把两个字符相同强行变为一个数学关系,怎么搞呢?
考虑这题是带通配符的,我们可以这样设:
\(C(x,y)=(A[x]-B[y])^2*A[x]*B[y]\)
因此,我们可以看出两个字符一样当且仅当\(C(x,y)=0\)
因此,我们再设一个函数\(P(x)\)表示\(B\)串以第\(x\)项为结尾的长度为\(m\)的子串是否与\(A\)串匹配,显然有:
\(P(x)=\sum_{i=0}^{m-1}C(i,x-m+i+1)\)
\(P(x)=\sum_{i=0}^{m-1}(A[i]-B[x-m+i+1])^2*A[i]*B[x-m+i+1]\)
后面那个式子写的太蛋疼了,我们把\(x-m+i+1\)设为\(j\)吧。
\(P(x)=\sum_{i=0}^{m-1}(A[i]-B[j])^2*A[i]*B[j]\)
大力展开得:
\(P(x)=\sum_{i=0}^{m-1}A[i]^3B[j]-2A[i]^2B[j]^2+A[i]B[j]^3\)
然后.....我们试着把\(\sum\)展开?
\(P(x)=\sum_{i=0}^{m-1}A[i]^3B[j]-\sum_{i=0}^{m-1}2A[i]^2B[j]^2+\sum_{i=0}^{m-1}A[i]B[j]^3\)
还是没法算啊......
诶,等下,如果我们把\(A\)串反转为\(A'\),肯定有\(A[i]=A'[m-i-1]\)
然后这个\((m-i-1)+(j)\)......不就是等于\(x\)嘛。
所以说我们马上就有:
\(P(x)=\sum_{i+j=x}A[i]^3B[j]-\sum_{i+j=x}2A[i]^2B[j]^2+\sum_{i+j=x}A[i]B[j]^3\)
哦豁,卷积,搞定~
时间复杂度\(O(nlogn)\)
搞定个鬼,这题要做7次FFT,常数爆大,我卡不进去
还请各位dalao赐教。
Code
#include<iostream>
#include<cstdio>
#include<complex>
#include<cmath>
#include<algorithm>
using namespace std;
const int M=300000+100;
const int N=M*4;
const double PI=acos(-1);
const double eps=1e-1;
typedef complex <double> cp;
cp omega(int K,int n)
{
return cp(cos(2*PI*K/n),sin(2*PI*K/n));
}
inline void FFT(cp a[],int n,bool type)
{
static int tmp[N],num=n-1,len;
while(num!=0) num/=2,len++;
for(int i=0,j;i<=n;i++)
{
for(j=0,num=i;j<len;j++)
tmp[j]=num%2,num/=2;
reverse(tmp,tmp+len);
for(j=0,num=0;j<len;j++)
num+=tmp[j]*(1<<j);
if(i<num) swap(a[i],a[num]);
}
for(int l=2;l<=n;l*=2)
{
int m=l/2;
cp x0=omega(1,l);
if(type==true) x0=conj(x0);
for(int i=0;i<n;i+=l)
{
cp x(1,0);
for(int j=0;j<m;j++,x*=x0)
{
cp temp=x*a[i+j+m];
a[i+j+m]=a[i+j]-temp;
a[i+j]=a[i+j]+temp;
}
}
}
}
char A[N],B[N];
int m,n,t=1;
cp S1[N],S2[N],S3[N],B1[N],B2[N],B3[N];
bool OK[N];
int main()
{
scanf("%d%d%s%s",&m,&n,A,B);
while(t<=(n+m)) t*=2;
reverse(A,A+m);
for(int i=0;i<t;i++)
A[i]=(A[i]=='*' or A[i]<'a' or A[i]>'z'?0:A[i]-'a'+1),
B[i]=(B[i]=='*' or B[i]<'a' or B[i]>'z'?0:B[i]-'a'+1);
for(int i=0;i<t;i++)
S1[i]=A[i],S2[i]=A[i]*A[i],S3[i]=A[i]*A[i]*A[i];
for(int i=0;i<t;i++)
B1[i]=B[i],B2[i]=B[i]*B[i],B3[i]=B[i]*B[i]*B[i];
FFT(S1,t,false);
FFT(S2,t,false);
FFT(S3,t,false);
FFT(B1,t,false);
FFT(B2,t,false);
FFT(B3,t,false);
for(int i=0;i<t;i++)
S3[i]*=B1[i];
for(int i=0;i<t;i++)
S1[i]*=B3[i];
for(int i=0;i<t;i++)
S2[i]*=B2[i];
for(int i=0;i<t;i++)
S3[i]+=S1[i]-2.0*S2[i];
FFT(S3,t,true);
int cnt=0;
for(int i=m-1;i<n;i++)
if(fabs(S3[i].real()/t)<eps)
OK[i]=true,cnt++;
printf("%d\n",cnt);
for(int i=m-1;i<n;i++)
if(OK[i]==true)
printf("%d ",i-m+1+1);
return 0;
}
[Luogu P4173]残缺的字符串 ( 数论 FFT)的更多相关文章
- Luogu P4173 残缺的字符串-FFT在字符串匹配中的应用
P4173 残缺的字符串 FFT在字符串匹配中的应用. 能解决大概这种问题: 给定长度为\(m\)的A串,长度为\(n\)的B串.问A串在B串中的匹配数 我们设一个函数(下标从\(0\)开始) \(C ...
- 洛谷P4173 残缺的字符串(FFT)
传送门 话说为什么字符串会和卷积扯上关系呢……到底得脑洞大到什么程度才能想到这种东西啊……大佬太珂怕了…… 因为通配符的关系,自动机已经废了 那么换种方式考虑,如果两个字符串每一位对应的编码都相等,那 ...
- luogu P4173 残缺的字符串
传送门 两种做法,一种是依次考虑每种字符,然后如果某个位置是该字符或者是\(*\)对应的值就是1,否则是0,然后把第一个串倒过来,fft卷积起来,最后看对应位置的值是否为m 然而上面那个做法在字符集大 ...
- P4173 残缺的字符串(FFT)
[Luogu4173] 题解 \(1.\)定义匹配函数 \(2.\)定义完全匹配函数 \(3.\)快速计算每一位的完全匹配函数值 #include<cstdio> #include< ...
- 洛谷 P4173 残缺的字符串 (FFT)
题目链接:P4173 残缺的字符串 题意 给定长度为 \(m\) 的模式串和长度为 \(n\) 的目标串,两个串都带有通配符,求所有匹配的位置. 思路 FFT 带有通配符的字符串匹配问题. 设模式串为 ...
- P4173 残缺的字符串(FFT字符串匹配)
P4173 残缺的字符串(FFT字符串匹配) P4173 解题思路: 经典套路将模式串翻转,将*设为0,设以目标串的x位置匹配结束的匹配函数为\(P(x)=\sum^{m-1}_{i=0}[A(m-1 ...
- 【BZOJ4259】残缺的字符串(FFT)
[BZOJ4259]残缺的字符串(FFT) 题面 给定两个字符串\(|S|,|T|\),两个字符串中都带有通配符. 回答\(T\)在\(S\)中出现的次数. \(|T|,|S|<=300000\ ...
- P4173 残缺的字符串 fft
题意:给你两个字符串,问你第一个在第二个中出现过多少次,并输出位置,匹配时是模糊匹配*可和任意一个字符匹配 题解:fft加速字符串匹配; 假设上面的串是s,s长度为m,下面的串是p,p长度为n,先考虑 ...
- BZOJ4259 残缺的字符串(FFT)
两个串匹配时相匹配的位置位置差是相同的,那么翻转一个串就变成位置和相同,卷积的形式. 考虑如何使用卷积体现两个位置能否匹配.一个暴力的思路是每次只考虑一种字符,将其在一个串中设为1,并在另一个串中将不 ...
随机推荐
- Go-The process cannot access the file because it is being used by another process.
where? Go程序在读取文件时候 why? 因为有其他进程也在读取和Go程序想要读取的文件,参数冲突 way? 关闭其他程序进程对该文件的读取操作
- 「面试」拿到B站的意向书
此次B站服务端开发面试之旅可谓惊险,不过通过对大部分面试题套路的掌握,不出意外还是拿下了,下面我们来看看这些骚题是不是常见的不能再常见的了.这些面试题看了就能面上?当然不是,只是通过这些题让自己知道所 ...
- spring-boot-route(八)整合mybatis操作数据库
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以使用简单的 XML ...
- 使用Cadence绘制PCB流程
转载:https://blog.csdn.net/hailin0716/article/details/47169799 之前使用过cadence画过几块板子,一直没有做过整理.每次画图遇到问题时,都 ...
- matlab中sum
来源:https://ww2.mathworks.cn/help/matlab/ref/sum.html?searchHighlight=sum&s_tid=doc_srchtitle#btv ...
- JavaFX FileChooser文件选择器、DirectoryChooser目录选择器
参考:https://www.yiibai.com/javafx/javafx_filechooser.html 参考:https://blog.csdn.net/dorma_bin/article/ ...
- Mac Idea你不知道的秘密
导读 工欲善其事必先利其器,日常工作中,知道这些Idea技巧,可以极大提高日常开发效率. 技巧篇 以下内容不分先后顺序 显示类中的方法 搜索 搜索方法,按两下shift 文字搜索,control+sh ...
- 在nginx下导出数据库数据
首先上干货 解决问题 set_time_limit(0); //设置脚本运行时间为不限制 因为php脚本默认时间为30秒 ini_set('memory_limit', -1); //取消脚本运行内存 ...
- 初始python模块
Python语言中,模块分为三类. 第一类:内置模块,也叫做标准库.此类模块就是python解释器给你提供的,比如我们之前见过的 time模块,os模块.标准库的模块非常多(200多个,每个模块又有很 ...
- 线程基本使用--Thread内部方法调用start
一个问题,下面的代码会如何运行 public class TraditionalThread { public static void main(String[] args) { System.out ...