题目传送门 - 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. nginx 80 端口 部署多个Web

    1.修改默认nginx.conf 文件 加入 include /usr/www/ngconfs/*.conf; 读取ngconfs文件下所有 *.conf文件 2.ngconfs 下多个文件创建 第二 ...

  2. unity游戏热更新

    链接:https://pan.baidu.com/s/1ggWP0OF 第 1 章 : 热更新技术学习介绍 课时1:101-热更新技术学习介绍 11:55 什么是热更新? 举例来说 游戏上线后,玩家下 ...

  3. Nginx-Tomcat搭建负载均衡(转载)

    一.   工具 nginx-1.8.0 apache-tomcat-6.0.33 二.    目标 实现高性能负载均衡的Tomcat集群: 三.    步骤 1.首先下载Nginx,要下载稳定版: 2 ...

  4. 数据分析---《Python for Data Analysis》学习笔记【02】

    <Python for Data Analysis>一书由Wes Mckinney所著,中文译名是<利用Python进行数据分析>.这里记录一下学习过程,其中有些方法和书中不同 ...

  5. jzoj6099. 【GDOI2019模拟2019.4.1】Dist

    题目链接:https://jzoj.net/senior/#main/show/6099 考虑直接统计某个点到其它所有点的距离和 我们先把整个团当成一个点建图,处理出任意两个团之间的距离\(dis(i ...

  6. Kubernetes 中的渐进式交付:蓝绿部署和金丝雀部署

    渐进式交付是持续交付的下一步, 它将新版本部署到用户的一个子集,并在将其滚动到全部用户之前对其正确性和性能进行评估, 如果不匹配某些关键指标,则进行回滚. 这里有一些有趣的项目,使得渐进式交付在 Ku ...

  7. 最大公约数和最小公倍数(Greatest Common Divisor and Least Common Multiple)

    定义: 最大公约数(英语:greatest common divisor,gcd).是数学词汇,指能够整除多个整数的最大正整数.而多个整数不能都为零.例如8和12的最大公因数为4. 最小公倍数是数论中 ...

  8. WEB-INF 目录

    WEB-INF 目录是必须的,其中包括: web.xml 文件,该 Web 基本配置,必须. classes 目录,存放 .class 文件,当然也可以将 .java 文件一并放进去. lib 目录, ...

  9. 解决ssh登录慢的问题

    修改文件/etc/ssh/sshd_config  : UseDNS no GSSAPIAuthentication no 重启服务 service sshd restart

  10. Python list和 np.Array 的转换关系

    一.List转String 1.str list转 string a_list = ["h","e","l","l",& ...