题面

传送门

bzoj上的这两题是一样的......

正文

我看到这道题,第一想法是跑魔改过的KMP,然后很快发现不可行

于是想换个角度思考

其实,本题最大的问题就在于通配符的存在:它可以匹配任意一个字符

那么我们考虑一个办法:令两个字符匹配成为“抵消”,那么数学上的抵消会让我们想到什么呢?

没错,0

我们令所有的通配符为0,让匹配变成两个字符相乘,那么乘出来零就“抵消”了

想到这里以后,一个非常自然的想法就是令所有的普通字符匹配也变成乘积为0的,但是这显然不可行,因为这个方法一定会导致不同字符乘起来也等于0(我们有26个字幕呢!!!)

现在这个问题就比较烦了,但是我们依然不能放弃希望

考虑0,除了作为非正非负数以外,它还有什么特性?

没错,零是一个整数

整数?整数......我们只要让匹配成功的字符,乘起来等于整数不就好了!

接下来的思路就比较清晰了:我们令第i种字母,在文本串(B串)中的值为i,在模式串(A串)中为$\frac 1i$,这样如果A串和B串某一位匹配,就会得到一个1

但是还有一个问题:如果遇到$4\ast\frac 12=2$这样的怎么办?

好说,我们令i等于10000+i就好了

我们把模式串A翻过来,然后让它与B串做FFT乘法

得到的第i位如果是整数,那么意味着从第i-n位开始的、长度为n的B串子串能与A匹配(n<i<=n*\2)

精度记得卡一卡,卡到1e-6就差不多了

貌似有的OJ只需要加1000?反正这是个玄学做法,总是能卡掉的吧......

Code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
inline int read(){
int re=0,flag=1;char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-') flag=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
return re*flag;
}
struct complex{
double x,y;
complex(double xx=0,double yy=0){x=xx;y=yy;}
complex operator +(const complex &b){return complex(x+b.x,y+b.y);}
complex operator -(const complex &b){return complex(x-b.x,y-b.y);}
complex operator *(const complex &b){return complex(x*b.x-y*b.y,x*b.y+y*b.x);}
}A[2000010],B[2000010];
const double pi=acos(-1.0);
int n,m,limit=1,cnt=0,r[2000010];
void fft(complex *a,double type){
int i,j,k,mid;complex x,y,w,wn;
for(i=0;i<limit;i++) if(i<r[i]) swap(a[i],a[r[i]]);
for(mid=1;mid<limit;mid<<=1){
wn=complex(cos(pi/mid),type*sin(pi/mid));
for(j=0;j<limit;j+=(mid<<1)){
w=complex(1,0);
for(k=0;k<mid;k++,w=w*wn){
x=a[j+k];y=w*a[j+k+mid];
a[j+k]=x+y;a[j+k+mid]=x-y;
}
}
}
}
vector<int>ans;
char s[300010];
int main(){
m=read();n=read();int i,tmp;
scanf("%s",s);
for(i=0;i<m;i++){
if(s[i]=='*') B[m-i].x=0;
else B[m-i].x=(1.0/(10001.0+double(s[i]-'a')));
}
scanf("%s",s);
for(i=0;i<n;i++){
if(s[i]=='*') A[i+1].x=0;
else A[i+1].x=(10001.0+double(s[i]-'a'));
}
while(limit<=(n+m)) limit<<=1,cnt++;
for(i=0;i<limit;i++) r[i]=((r[i>>1]>>1)|((i&1)<<(cnt-1)));
fft(A,1);fft(B,1);
for(i=0;i<=limit;i++) A[i]=A[i]*B[i];
fft(A,-1);
for(i=m+1;i<=n+1;i++){
A[i].x/=(double)limit;tmp=(int)(A[i].x+0.5);
if(abs(A[i].x-(double(tmp)))<=1e-6) ans.push_back(i-m);
}
printf("%d\n",ans.size());
for(i=0;i<ans.size();i++) printf("%d ",ans[i]);
}

[bzoj4259][bzoj4503] 残缺的字符串 [FFT]的更多相关文章

  1. 【BZOJ4259】残缺的字符串 FFT

    [BZOJ4259]残缺的字符串 Description 很久很久以前,在你刚刚学习字符串匹配的时候,有两个仅包含小写字母的字符串A和B,其中A串长度为m,B串长度为n.可当你现在再次碰到这两个串时, ...

  2. 【bzoj4259】 残缺的字符串 FFT

    又是一道FFT套路题 思路可以参考bzoj4503,题解 我们对串S和串T中出现的*处全部赋值为0. 反正最终的差异度式子大概就是 $C[i]=\sum_{j=0}^{|T|-1}S[i+j]T[j] ...

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

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

  4. 【BZOJ4259】残缺的字符串

    [BZOJ4259]残缺的字符串 Description 很久很久以前,在你刚刚学习字符串匹配的时候,有两个仅包含小写字母的字符串A和B,其中A串长度为m,B串长度为n.可当你现在再次碰到这两个串时, ...

  5. luoguP4173 残缺的字符串 FFT

    luoguP4173 残缺的字符串 FFT 链接 luogu 思路 和昨天做的题几乎一样. 匹配等价于(其实我更喜欢fft从0开始) \(\sum\limits_{i=0}^{m-1}(S[i+j]- ...

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

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

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

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

  8. BZOJ 4259: 残缺的字符串 [FFT]

    4259: 残缺的字符串 题意:s,t,星号任意字符,匹配方案数 和上题一样 多乘上一个\(a_{j+i}\)就行了 #include <iostream> #include <cs ...

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

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

随机推荐

  1. 2017.12.25 Linux系统的使用

    Linux系统的使用 现在标配的系统是 Linux + Nginx + PHP + MySQL ,这样的配置越来越多的大公司在用的了说到配置不同的是一个公司的规约,比如说挂载一般分为2个盘, / 下面 ...

  2. python_44_文件属性

    #打印文件属性信息 import os#os.stat()返回的文件属性元组元素的含义 filestats=os.stat('yesterday')#获取文件/目录的状态 print(filestat ...

  3. spring mvc + swagger 配置

    首先,添加mvc框架(略)以及Swagger Maven依赖: <dependency> <groupId>io.springfox</groupId> <a ...

  4. windows下sorl安装

    1. JDK要求 Solr 4.10 要求JDK版本必须是1.7或更高. 2. 下载 下载地址: http://www.apache.org/dyn/closer.cgi/lucene/solr/ 下 ...

  5. 问题001:Java软件,属于系统软件还是应用软件呢?

    在学习Java前要掌握的一些小问题: 问题一:Java软件,属于系统软件还是应用软件呢? java语言应用在计算机系统上,首先应知道计算机系统分为几部分? 计算机系统由硬件系统和软件系统两部分构成.硬 ...

  6. AFN post的数据编码格式问题

    想到写任何关于AFN的东西其实我是拒绝的,因为自己这也是第一次用,毕竟AFN现在是最为流行的网络框架了,害怕自己理解的有误,所以不敢造次! 先在这里大致讲解一下过程吧,后期发现了再更正(主要是想让看官 ...

  7. linux分区之ext2,ext3,ext4,gpt

    linux分区之ext2,ext3,ext4,gpt 2013-07-10 12:00:24 标签:ext3 gpt 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明 ...

  8. mysql 绿色版 安装

    1.下载mysql的绿色版压缩包.(自行百度) 2.自行规划目录解压 3.安装 注意:我遇到的两种版本的安装方法(暂时按照解压后的目录中是否含有data目录来区分) 3.1 无data目录(我用到的的 ...

  9. Thinkphp5封装上传图片

    <?php namespace app\api\controller; use think\Controller; use think\Db; class Plus extends Base{ ...

  10. .NET 执行命令行乱码

    Process可以运行命令行内容儿不用担心会弹出命令行窗口 需要读取命令行结果时,如果不注意内容编码,就会出现读取的结果出现乱码 读取StandardOutput结果时需要指定StandardOutp ...