题面

传送门

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. 生成.m文件的python代码中出现的错误

    错误代码 import tempfile import subprocess import shlex import os import numpy as np import scipy.io scr ...

  2. python_6_if

    _username='qi' _password='abc123' username=input("username:") password=input('password:') ...

  3. python_78_软件目录结构规范

    一定要看http://www.cnblogs.com/alex3714/articles/5765046.html #print(__file__)#打印的是文件的相对路径 import os pri ...

  4. EM理解(转)

    EM是我一直想深入学习的算法之一,第一次听说是在NLP课中的HMM那一节,为了解决HMM的参数估计问题,使用了EM算法.在之后的MT中的词对齐中也用到了.在Mitchell的书中也提到EM可以用于贝叶 ...

  5. JoinQuant策略代码示例

    总体回测前 ''' ================================================================================ 总体回测前 === ...

  6. vue学习之路 - 4.基本操作(下)

    vue学习之路 - 4.基本操作(下) 简述:本章节主要介绍 vue 的一些其他常用指令. Vue 指令 这里将 vue 的指令分为系统内部指令(vue 自带指令)和用户自定义指令两种. 系统内部指令 ...

  7. Java 解决IE浏览器下载文件,文件名出现乱码问题

    /** * 区分ie 和其他浏览器的下载文件乱码问题 * @param request * @param fileName * @return */ public String getFileName ...

  8. js时间转换

    1. 将时间戳转换成日期格式 // 简单的一句代码 var date = new Date(时间戳); //获取一个时间对象 /** 1. 下面是获取时间日期的方法,需要什么样的格式自己拼接起来就好了 ...

  9. opengl 学习的链接,以后需要可以再来查需要的

    记录一些好的opengl学习站点,以供日后查阅: modern opengl tutorial : 一个英国的opengl学习网站 上面网站的中文版 日后发现新的再更新

  10. Girls and Boys-hdu 1068

    Girls and Boys Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...