题目传送门 - BZOJ4503


题意概括

  给定两个字符串S和T,回答T在S中出现了几次,在哪些位置出现。注意T中可能有?字符,可以匹配任何字符。


题解

  首先,假装你已经知道了这是一道$FFT$题。

  考虑怎样$FFT$。

  字符串匹配的时候,对于匹配成功的对应字母的编号(比如分别是$i$和$j$),满足了$i-j$都相同。但是我们需要的是$i+j$都相等。

  于是我们用$FFT$的经典套路,翻转$T$串。

  我们构造一个卷积:

  $$\sum_{i=0}^{n}\sum_{j=0}^{m}(S_{i}-T_{j})^{2}S_{i}T_{j}$$

  把他表示成这个形式:

  $$h_i=\sum_{j=0}^j (S_{j}-T_{i-j})^{2}S_{j}T_{i-j}$$

  其中对应的字符$c$如果为'?'值为$0$,否则为$c-'a'+1$。

  这样的话,如果$h_i=0$的话那么就可以第$i$位开始匹配。

  那么我们考虑求解这个式子。

  我们只要展开一下:

  $(S_i-T_j)^{2}S_{i}T_{j}\ = \ s_{i}^{3}t_{j}-2s_{i}^{2}t_{j}^{2}+s_{i}t_{j}^{3}$

  然后变成了三组卷积,一坨$FFT$即可。

  $Time:9000^+ MS$

  震惊!

  本题还有更优秀的解法。

  对于没有问号的,我们$KMP$解决。

  对于有问好的,暴搜解决。

  复杂度极其优越。

  $Time:100^- MS$


代码

#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <vector>
using namespace std;
const int N=1<<18;
const double PI=acos(-1.0);
struct C{
double r,i;
C(){r=i=0;}
C(double a,double b){r=a,i=b;}
C operator + (C a){return C(r+a.r,i+a.i);}
C operator - (C a){return C(r-a.r,i-a.i);}
C operator * (C a){return C(r*a.r-i*a.i,r*a.i+i*a.r);}
}a[N],b[N],a1[N],b1[N],a2[N],b2[N],a3[N],b3[N],w[N];
int A,B,n,L,res[N],R[N];
double tot[N];
vector <int> ans;
char s[N],t[N];
void FFT (C a[N],int n){
for (int i=0;i<n;i++)
if (i<R[i])
swap(a[i],a[R[i]]);
for (int d=1,t=n>>1;d<n;d<<=1,t>>=1)
for (int i=0;i<n;i+=(d<<1))
for (int j=0;j<d;j++){
C tmp=w[t*j]*a[i+j+d];
a[i+j+d]=a[i+j]-tmp;
a[i+j]=a[i+j]+tmp;
}
}
int main(){
scanf("%s%s",s,t);
A=strlen(s),B=strlen(t);
for (int i=0;i<B/2;i++)
swap(t[i],t[B-i-1]);
// (s-t)(s-t)st
//=ssst-2sstt+sttt
for (int i=0;i<n;i++)
a[i]=b[i]=C(0,0);
for (int i=0;i<A;i++)
a[i].r=s[i]-'a'+1;
for (int i=0;i<B;i++)
b[i].r=t[i]=='?'?0:(t[i]-'a'+1);
for (n=1,L=0;n<=A+B;n<<=1,L++);
for (int i=0;i<n;i++){
R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));
w[i]=C(cos(2*i*PI/n),sin(2*i*PI/n));
a1[i]=a[i]*a[i]*a[i];
b1[i]=b[i];
a2[i]=a[i]*a[i];
b2[i]=b[i]*b[i];
a3[i]=a[i];
b3[i]=b[i]*b[i]*b[i];
}
FFT(a1,n),FFT(b1,n),FFT(a2,n),FFT(b2,n),FFT(a3,n),FFT(b3,n);
for (int i=0;i<n;i++){
a1[i]=a1[i]*b1[i];
a2[i]=a2[i]*b2[i];
a3[i]=a3[i]*b3[i];
w[i].i*=-1.0;
}
FFT(a1,n),FFT(a2,n),FFT(a3,n);
for (int i=0;i<n;i++)
tot[i]=a1[i].r-2.0*a2[i].r+a3[i].r;
for (int i=0;i<n;i++)
res[i]=int(tot[i]+0.5);
ans.clear();
for (int i=B-1;i<A;i++)
if (!res[i])
ans.push_back(i-B+1);
printf("%d\n",ans.size());
for (vector <int>::iterator i=ans.begin();i!=ans.end();i++)
printf("%d\n",*i);
return 0;
}

  

BZOJ4503 两个串 多项式 FFT的更多相关文章

  1. 2019.02.06 bzoj4503: 两个串(fft)

    传送门 题意简述:给两个字符串s,ts,ts,t,ttt中可能有通配符,问ttt在sss出现的次数和所有位置. 思路:一道很熟悉的题,跟bzoj4259bzoj4259bzoj4259差不多的. 然后 ...

  2. BZOJ4503 两个串 【fft】

    题目链接 BZOJ4503 题解 水水题. 和残缺的字符串那题几乎是一样的 同样转化为多项式 同样TLE 同样要手写一下复数才A #include<algorithm> #include& ...

  3. 【BZOJ4503】两个串(FFT)

    [BZOJ4503]两个串(FFT) 题面 给定串\(S\),以及带通配符的串\(T\),询问\(T\)在\(S\)中出现了几次.并且输出对应的位置. \(|S|,|T|<=10^5\),字符集 ...

  4. bzoj4503: 两个串 bitset

    目录 题目链接 题解 代码 题目链接 bzoj4503: 两个串 题解 暴一发bitset f[i][j] 表示 S[1..i] 是否有个后缀能匹配 T[1..j] 那么假设 S[i+1] 能匹配 T ...

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

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

  6. BZOJ4503: 两个串

    Description 兔子们在玩两个串的游戏.给定两个字符串S和T,兔子们想知道T在S中出现了几次, 分别在哪些位置出现.注意T中可能有“?”字符,这个字符可以匹配任何字符. Input 两行两个字 ...

  7. 【BZOJ 4503】4503: 两个串 (FFT)

    4503: 两个串 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 497  Solved: 226 Description 兔子们在玩两个串的游戏.给 ...

  8. BZOJ 4503 两个串(FFT)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4503 [题目大意] 给出S串和T串,计算T在S中出现次数,T中有通配符'?'. [题解 ...

  9. BZOJ4503: 两个串(bitset字符串匹配)

    题意 题目链接 Sol Orz xudyh F个毛T啊..直接bitset一波就赢了啊...(虽然复杂度很假) 就是记录匹配串中每个元素出现的位置,将第\(i\)个位置的bitset右移\(i\)位后 ...

随机推荐

  1. shell之获取终端信息

    #!/bin/bash #tput和stty是两款终端处理工具 #获取列数和行数 tput cols tput lines #打印当前终端名 tput longname #移动光标 移动光标到100 ...

  2. scrapy之使用LinkExtractor提取链接

    一.概述: 在页面含有少量链接时,使用selector来提取信息就可以,但如果链接特别多时,就需要用LinkExtractor来提取. 二.LinkExtractor构造器的各个参数: 1.allow ...

  3. The Preliminary Contest for ICPC China Nanchang National Invitational and International Silk-Road Programming Contest

    打网络赛 比赛前的准备工作要做好 确保 c++/java/python的编译器能用 打好模板,放在桌面 A. PERFECT NUMBER PROBLEM #include <cstdio> ...

  4. C# 操作SQL Server 公共库

    基本够用,存一下,以后找起来方便 public abstract class DB { //数据库连接字符串(config来配置) protected static string connection ...

  5. IIC协议理解(转)

    目录 IIC协议理解(转) 个人小结记录 (记一下这个就够了) 以下为转载记录 概述 概述 输出级 主设备与从设备 速率 时序 空闲状态 起始位与停止位 数据的有效性 数据的传送 工作过程 主设备向从 ...

  6. Ceph集群搭建及Kubernetes上实现动态存储(StorageClass)

    集群准备 ceph集群配置说明   节点名称 IP地址 配置 作用 ceph-moni-0 10.10.3.150 centos7.5 4C,16G,200Disk 管理节点,监视器 monitor ...

  7. Linux记录-open-falcon开源监控系统部署

    参考https://book.open-falcon.org/zh_0_2/quick_install/prepare.html一.安装后端1.环境准备yum -y install redisyum ...

  8. TPS、并发用户数、吞吐量关系

    TPS.并发用户数.吞吐量关系 摘要 主要描述了在性能测试中,关于TPS.并发用户数.吞吐量之间的关系和一些计算方法. loadrunner TPS 目录[-] 一.系统吞度量要素: 二.系统吞吐量评 ...

  9. Docker下安装rabbitmq

    拉取镜像 docker pull rabbitmq:-management 启动镜像(默认用户名密码),默认guest 用户,密码也是 guest docker run -d --: -p : rab ...

  10. Groovy 设计模式 -- 保镖模式

    Bouncer Pattern http://groovy-lang.org/design-patterns.html#_bouncer_pattern 保镖模式主要负责对函数的输入参数的合法性检查, ...