题面

传送门:洛咕


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)的更多相关文章

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

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

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

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

  3. luogu P4173 残缺的字符串

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

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

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

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

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

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

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

  7. 【BZOJ4259】残缺的字符串(FFT)

    [BZOJ4259]残缺的字符串(FFT) 题面 给定两个字符串\(|S|,|T|\),两个字符串中都带有通配符. 回答\(T\)在\(S\)中出现的次数. \(|T|,|S|<=300000\ ...

  8. P4173 残缺的字符串 fft

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

  9. BZOJ4259 残缺的字符串(FFT)

    两个串匹配时相匹配的位置位置差是相同的,那么翻转一个串就变成位置和相同,卷积的形式. 考虑如何使用卷积体现两个位置能否匹配.一个暴力的思路是每次只考虑一种字符,将其在一个串中设为1,并在另一个串中将不 ...

随机推荐

  1. (转载)什么是B+树?

    本文转载自网络. 如有侵权,请联系处理!  

  2. GAN生成的评价指标 Evaluation of GAN

    传统方法中,如何衡量一个generator ?-- 用 generator 产生数据的 likelihood,越大越好. 但是 GAN 中的 generator 是隐式建模,所以只能从 P_G 中采样 ...

  3. Code Forces 1030E

    题目大意: 给你n个数,你可以交换一个数的任意二进制位,问你可以选出多少区间经过操作后异或和是0. 思路分析: 根据题目,很容易知道,对于每个数,我们可以无视它的1在那些位置,只要关注它有几个1即可, ...

  4. MySQL 之 innodb 日志管理 -- 1. 基本日志文件

    1.基本日志文件分类 错误日志(error log) 慢查询日志日志(slow query log) 二进制日志(binlog) 查询日志(general log) 2.错误日志 主要包括mysql的 ...

  5. C# 中 System.Index 结构体和 Hat 运算符(^)的全新用法

    翻译自 John Demetriou 2019年2月17日 的文章 <C# 8 – Introducing Index Struct And A Brand New Usage For The ...

  6. Python+Appium自动化测试(3)-编写自动化脚本

    之前一篇博客已经讲述怎样手动使用appium-desktop启动测试机上的app,但我们实际跑自动化脚本的过程中,是需要用脚本调用appium启动app的,接下来就尝试写Python脚本启动app并登 ...

  7. react中 受控组件和 非受控组件 浅析

    一 受控组件 顾名思义,受控 也就是能够被控制,简而言之也就是 该组件ui的显示或者内部state逻辑的变化依赖外部的 props的传入. 二 非受控组件 顾名思义,非受控,也就是内部的视图变化,st ...

  8. mysql 登陆与退出

    Mysql登陆与退出 登陆参数 登陆命令 mysql -uroot -p 回车输入密码 退出有三个命令:  exit  quit  \q 修改mysql提示符 连接mysql客户端时通过参数指定: 登 ...

  9. 微信小程序 - 重置checkbox样式

    /* 未选中的 背景样式 */ checkbox .wx-checkbox-input { border-radius: 50%;/* 圆角 */ width: 30rpx; /* 背景的宽 */ h ...

  10. 【纯水题】POJ 1852 Ants

    题目大意 有一根长\(L\)厘米米的水平木棍上有\(n\)个蚂蚁,它们以每秒1cm/s的爬(fei)行(ben)到木棍的一端,之后掉下去. 给出每个蚂蚁的起始位置,但是不知道它们爬行的方向.相向而行的 ...