题目描述

很久很久以前,在你刚刚学习字符串匹配的时候,有两个仅包含小写字母的字符串A和B,其中A串长度为m,B串长度为n。可当你现在再次碰到这两个串时,这两个串已经老化了,每个串都有不同程度的残缺。

你想对这两个串重新进行匹配,其中A为模板串,那么现在问题来了,请回答,对于B的每一个位置i,从这个位置开始连续m个字符形成的子串是否可能与A串完全匹配?

题解

带通配符的字符串匹配问题。

我们先把通配符设为0,考虑如果匹配串中的一段和模式串完全匹配,那么必然满足∑(a[i]-b[i])^2*a[i]*b[i]=0。

很容易发现这是个卷积,那么把任意一个串倒过来FFT一下就好了。

这题还卡我精度。。。

代码

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define N 600002
#define double long double
using namespace std;
typedef long long ll;
int l,L,n,m,rev[N],ans[N];
char s1[N],s2[N];
const double pai=acos(-1.0);
struct fs{
double x,y;
fs(double xx=,double yy=){x=xx;y=yy;}
fs operator +(const fs &b)const{return fs{x+b.x,y+b.y};}
fs operator -(const fs &b)const{return fs{x-b.x,y-b.y};}
fs operator *(const fs &b)const{return fs{x*b.x-y*b.y,x*b.y+y*b.x};}
}a[N],b[N],c[N],d[N],e[N];
inline void FFT(fs *a,int tag){
for(int i=;i<l;++i)if(i>rev[i])swap(a[i],a[rev[i]]);
for(int i=;i<l;i<<=){
fs wn(cos(pai/i),tag*sin(pai/i));
for(int j=;j<l;j+=(i<<)){
fs w(,);
for(int k=;k<i;++k,w=w*wn){
fs x=a[j+k],y=a[i+j+k]*w;
a[j+k]=x+y;a[i+j+k]=x-y;
}
}
}
}
int main(){
scanf("%d%d",&m,&n);
l=;L=;
while(l<n)l<<=,L++;
for(int i=;i<l;++i)rev[i]=(rev[i>>]>>)|((i&)<<(L-));
scanf("%s%s",s2,s1);
for(int i=;i<n;++i)if(s1[i]=='*')s1[i]=;else s1[i]-='A';
for(int i=;i<m;++i)if(s2[i]=='*')s2[i]=;else s2[i]-='A';
reverse(s2,s2+m);
for(int i=;i<n;++i)a[i].x=1ll*s1[i]*s1[i]*s1[i];
for(int i=;i<m;++i)b[i].x=s2[i];
FFT(a,);FFT(b,);
for(int i=;i<l;++i)c[i]=a[i]*b[i];
FFT(c,-);
for(int i=;i<l;++i)c[i].x=(ll)(c[i].x/l+0.4);
memset(a,,sizeof(a));memset(b,,sizeof(b));
for(int i=;i<n;++i)a[i].x=s1[i]*s1[i];
for(int i=;i<m;++i)b[i].x=s2[i]*s2[i];
FFT(a,);FFT(b,);
for(int i=;i<l;++i)d[i]=a[i]*b[i]*fs(,);
FFT(d,-);
for(int i=;i<l;++i)d[i].x=(ll)(d[i].x/l+0.4);
memset(a,,sizeof(a));memset(b,,sizeof(b));
for(int i=;i<n;++i)a[i].x=s1[i];
for(int i=;i<m;++i)b[i].x=1ll*s2[i]*s2[i]*s2[i];
FFT(a,);FFT(b,);
for(int i=;i<l;++i)e[i]=a[i]*b[i];
FFT(e,-);
for(int i=;i<l;++i)e[i].x=(ll)(e[i].x/l+0.4);
for(int i=m-;i<n;++i)if(c[i].x+e[i].x-d[i].x==)ans[++ans[]]=i-m+;
printf("%d\n",ans[]);
for(int i=;i<=ans[];++i)printf("%d ",ans[i]);
return ;
}

BZOJ4259残缺的字符串的更多相关文章

  1. CF528D Fuzzy Search 和 BZOJ4259 残缺的字符串

    Fuzzy Search 给你文本串 S 和模式串 T,求 S 的每个位置是否能模糊匹配上 T. 这里的模糊匹配指的是把 T 放到 S 相应位置上之后,T 中每个字符所在位置附近 k 个之内的位置上的 ...

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

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

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

    Description 很久很久以前,在你刚刚学习字符串匹配的时候,有两个仅包含小写字母的字符串A和B,其中A串长度为m,B串长度为n.可当你现在再次碰到这两个串时,这两个串已经老化了,每个串都有不同 ...

  4. BZOJ4259 残缺的字符串 【fft】

    题目 很久很久以前,在你刚刚学习字符串匹配的时候,有两个仅包含小写字母的字符串A和B,其中A串长度为m,B串长度为n.可当你现在再次碰到这两个串时,这两个串已经老化了,每个串都有不同程度的残缺. 你想 ...

  5. BZOJ4259: 残缺的字符串 & BZOJ4503: 两个串

    [传送门:BZOJ4259&BZOJ4503] 简要题意: 给出两个字符串,第一个串长度为m,第二个串长度为n,字符串中如果有*字符,则代表当前位置可以匹配任何字符 求出第一个字符串在第二个字 ...

  6. BZOJ4259 残缺的字符串 多项式 FFT

    原文链接http://www.cnblogs.com/zhouzhendong/p/8798532.html 题目传送门 - BZOJ4259 题意 给你两个串,用其中一个来匹配另一个.问从母串的那些 ...

  7. [BZOJ4259]残缺的字符串

    Description: 给定两个带通配符的串,求可能出现几次匹配,以及这些匹配位置 Hint: \(n \le 3*10^5\) Solution: 定义匹配函数 \(P(x)=\sum_{i=x} ...

  8. 2018.11.17 bzoj4259: 残缺的字符串(fft)

    传送门 fftfftfft套路题. 我们把aaa ~ zzz映射成111 ~ 262626,然后把∗*∗映射成000. 考虑对于两个长度都为nnn的字符串A,BA,BA,B. 我们定义一个差异函数di ...

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

    题意 题目链接 Sol 知道FFT能做字符串匹配的话这就是个裸题了吧.. 考虑把B翻转过来,如果\(\sum_{k = 0}^M (B_{i - k} - A_k)^2 * B_{i-k}*A_k = ...

随机推荐

  1. OpenUDID 和 IDFA 比较

    iOS标识符 现今来比较下,不同情况下两种标识符的变化情况.以下试验,每种标识符均分为存于Keychain和未存于Keychain的两种情况做比较. 广告标识符(IDFA-identifierForI ...

  2. WebView断网提示

    转载请标明出处,维权必究:https://www.cnblogs.com/tangZH/p/9913968.html 重写WebViewClient中的方法,然后WebView.setWebViewC ...

  3. Android ScrollView和ListView滑动冲突解决记录

    private int mLastX; private int mLastY; public View.OnTouchListener onTouchListener = new View.OnTou ...

  4. 【原】Java学习笔记017 - 面向对象

    package cn.temptation; public class Sample01 { public static void main(String[] args) { // 继承关系中的pri ...

  5. 【PAT】B1018 锤子剪刀布

    抄的柳婼小姐姐的,感觉三个数求最大那里用的真棒 #include <stdio.h> int main() { int N; scanf("%d", &N); ...

  6. (转载)最完整的自动化测试流程:Python编写执行测试用例及定时自动发送最新测试报告邮件

    今天笔者就要归纳总结下一整套测试流程,从无到有,实现零突破,包括如何编写测试用例,定时执行测试用例,查找最新生成的测试报告文件,自动发送最新测试报告邮件,一整套完整的测试流程.以后各位只要着重如何编写 ...

  7. java常用问题排查工具

    一:jstack找到最耗cpu的线程并定位代码 1.ps -ef|grep java 或者 jps -l 得到进程pid 2.找到该进程内最耗cpu的线程,我一般使用: top -Hp pid 3.c ...

  8. gulp结合Thinkphp配置

    gulpfile.js文件 /*! * gulp * $ npm install gulp gulp-ruby-sass gulp-cached gulp-uglify gulp-rename gul ...

  9. javaScript判断手机型号

    window.onload = function () { alert("1"); var u = navigator.userAgent; if (u.indexOf('Andr ...

  10. Golang 入门系列(六)理解Go中的协程(Goroutine)

    前面讲的都是一些Go 语言的基础知识,感兴趣的朋友可以先看看之前的文章.https://www.cnblogs.com/zhangweizhong/category/1275863.html. 今天就 ...