【BZOJ4503】两个串(FFT)

题面

给定串\(S\),以及带通配符的串\(T\),询问\(T\)在\(S\)中出现了几次。并且输出对应的位置。

\(|S|,|T|<=10^5\),字符集大小为\(26\)

题解

先来考虑没有通配符怎么匹配。别跟我说KMP!!

根据前面几个题目的套路,我们可以把每个字符分开来考虑,然后将\(T\)串反转,将有这个字符的位置变成\(1\),然后\(FFT\),就可以知道在这一段里面这个字符匹配上了多少个,然后把每个字符求个和,检查是否恰好匹配了\(|T|\)个。

通配符此时并不需要考虑。

时间复杂度\(O(26nlogn)\)

当然,如果您真的这么写了,那么肯定\(T\)飞了。\(FFT\)自带巨大常数。对于字符集很小的时候上述方法是可行的,字符集很大的时候就不能这么做了。

所以我们考虑如何只做一遍\(FFT\)。(没有通配符的情况下)

每个字符当然不能动了,所以把他们对应成数字。如果匹配上了怎么办?那就是上下两个对应的数字相等,可以考虑作差。但是又发现作差可能会使得几个正数和几个负数相加变成\(0\),所以考虑平方。

所以,我们定义每个位置的函数值\(f(x)=\sum_{i=1}^{|T|}(S[x+i-1]-T[i])^2\)

将\(T\)串反转,平方项拆开之后,就变成了两个卷积+一个常数项的形式,直接\(FFT\)然后求和,检查最后的函数值是否为\(0\)就行了。

现在有了通配符,我们不妨令\(a..z\)对应的数字为\(1..26\)。通配符无论给它一个什么数字,它和上面的字符的差的平方一定不为\(0\)。

所以我们换种方法考虑,把通配符对应的数字设为\(0\),但是这样差的平方不是\(0\),所以我们就在上面那个式子后面乘上一个\(T[i]\)的权值,如果此时是通配符就会乘\(0\),从而也变成了\(0\)。这样一来,原来的式子就变成了\(f(x)=\sum_{i=1}^{|T|}(S[x+i-1]-T[i])^2T[i]\)

拆开后是两个卷积+一个常数项的形式,\(FFT\)即可。

时间复杂度\(O(nlogn)\)

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 333333
const double Pi=acos(-1);
struct Complex{double a,b;}A1[MAX],B1[MAX],A2[MAX],B2[MAX],W[MAX],F[MAX];
Complex operator+(Complex a,Complex b){return (Complex){a.a+b.a,a.b+b.b};}
Complex operator-(Complex a,Complex b){return (Complex){a.a-b.a,a.b-b.b};}
Complex operator*(Complex a,Complex b){return (Complex){a.a*b.a-a.b*b.b,a.a*b.b+a.b*b.a};}
int n,m,r[MAX],N,Z;
int pos[MAX],ans,l;
char S[MAX],T[MAX];
void FFT(Complex *P,int opt)
{for(int i=1;i<N;++i)if(i<r[i])swap(P[i],P[r[i]]);for(int i=1;i<N;i<<=1)for(int p=i<<1,j=0;j<N;j+=p)for(int k=0;k<i;++k){Complex w=(Complex){W[N/i*k].a,W[N/i*k].b*opt};Complex X=P[j+k],Y=w*P[j+k+i];P[j+k]=X+Y;P[i+j+k]=X-Y;}if(opt==-1)for(int i=0;i<N;++i)P[i].a/=N;
}
int main()
{scanf("%s",S);scanf("%s",T);n=strlen(S);m=strlen(T);for(N=1;N<=(n+m-2);N<<=1)++l;for(int i=0;i<N;++i)r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));for(int i=1;i<N;i<<=1)for(int k=0;k<i;++k)W[N/i*k]=(Complex){cos(k*Pi/i),sin(k*Pi/i)};for(int i=0;i<n;++i)A1[i].a=(S[i]-96)*(S[i]-96),A2[i].a=2*(S[i]-96);for(int i=0;i<m;++i){int x=((T[m-i-1]=='?')?0:(T[m-i-1]-96));B1[i].a=x;B2[i].a=x*x;Z+=x*x*x;}FFT(A1,1);FFT(B1,1);FFT(A2,1);FFT(B2,1);for(int i=0;i<N;++i)F[i]=A1[i]*B1[i]-A2[i]*B2[i];FFT(F,-1);for(int i=m-1;i<n;++i)if((int)(F[i].a+0.5+Z)==0)pos[++ans]=i-m+1;printf("%d\n",ans);for(int i=1;i<=ans;++i)printf("%d\n",pos[i]);return 0;
}

转载于:https://www.cnblogs.com/cjyyb/p/8798446.html

【BZOJ4503】两个串(FFT)相关推荐

  1. Bzoj4503 两个串

    Time Limit: 20 Sec  Memory Limit: 256 MB Submit: 398  Solved: 190 Description 兔子们在玩两个串的游戏.给定两个字符串S和T ...

  2. BZOJ4503:两个串(bitset)

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

  3. BZOJ4503 两个串 【fft】

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

  4. bzoj4503: 两个串

    我又变成sb了 首先通过%可以得到一个这样的柿子: 设s1是模版串,s2是匹配串,j表示模版串以j为起始的子串 fj(0<j<=s1len-s2len) =sigema(i=0~s2len ...

  5. hdu 1867 求两个串的和最小 ,KMP

    题意:       给你两个字符串,让你求str1+str2,就是把1的后面和2的前面重叠的地方只显示一遍就行了 abc + bcd = abcd,要求和的长度最小,和最小的前提下求字典序最小,还有就 ...

  6. 2019牛客多校第四场 I题 后缀自动机_后缀数组_求两个串de公共子串的种类数

    目录 求若干个串的公共子串个数相关变形题 对一个串建后缀自动机,另一个串在上面跑同时计数 广义后缀自动机 后缀数组 其他:POJ 3415 求两个串长度至少为k的公共子串数量 @(牛客多校第四场 I题 ...

  7. 递归法:求两个串的最大公共子序列的长度

    问题:求两个串的最大公共子序列的长度 举例: 子串: abcgxs 与sabxfh 其最大公共子序列的为abx,长度为3 public class Zixulie {public static int ...

  8. Simpsons’ Hidden Talents(KMP ,两个串的前后缀匹配)

    Simpsons' Hidden Talents 题目 给两个串,求S1的前缀和S2的后缀的最大匹配 思路 拼接两个串,处理出nxt数组,nxt[k] 即为所求,因为它们的最大匹配不能超过原串的长度, ...

  9. 题6:两个串的字符集是否相等

    题目: 只要出现的字符集相同就相等,不在乎数量. 思路: 借助辅助数组,先扫描第一个字符串,将出现的字符转换为辅助数组的下标并标记为1 package 字符串问题;import java.util.H ...

  10. [颓废史]蒟蒻的刷题记录

    QAQ蒟蒻一枚,其实我就是来提供水题库的. 以下记录从2016年开始. 1.1 1227: [SDOI2009]虔诚的墓主人 树状数组+离散化 3132: 上帝造题的七分钟 树状数组 二维区间加减+查 ...

最新文章

  1. PolarSSL 1.2.0 发布,SSL 加密库
  2. git查看一个文件的历史记录
  3. 边界测试——让BUG现形
  4. Hi3516A开发--i2c tools安装和使用
  5. 如何快速精确的和leader沟通
  6. 2G,3G ,4G 到 5G 变了什么 ?
  7. Ubuntu常用C语言IDE,Ubuntu下常用IDE的安装
  8. linux init进程源码,Android启动Init进程源码分析
  9. 刘洪波《英文字根词源精讲》完整目录
  10. kubernetes dashboard
  11. java参数防篡改,Java程序防篡改器设计方案
  12. 中国科学: 信息科学 中文模板2019 CCT-LaTeX texlive2019 成功编译
  13. 如何用计算机求特征值特征向量,特征值和特征向量计算器为4X4的实矩阵
  14. 用 CSS3 做一个流星雨动画
  15. wordpress企业网站主题仿制04-wordpress企业网站产品页面新闻页面仿制
  16. linux修改sda3时间,Linux服务器磁盘占满问题解决(/dev/sda3 满了)
  17. android动画原理,最详细的解释小白也能听懂,值得收藏!
  18. QGIS常用图源(谷歌中国、mapbox、esri、天地图等)(weixin公众号【图说GIS】)
  19. ABAP角度看SAP货币和汇率
  20. Detecting tiny objects in aerial images: A normalized Wasserstein distance and a new benchmark(论文导读)

热门文章

  1. css的布局模型(三)—层模型
  2. Android Sqlite数据库操作
  3. [转]何为C10K问题
  4. Java 服务器端支持断点续传的源代码
  5. Python如何输出格式清晰的dict
  6. 工具 | Axure基础操作 No.6
  7. linux下source filename,./filename,. filename,......
  8. Java并发AtomicIntegerArray类
  9. 功能选中jquery实现全选反选功能
  10. Silverlight 2 跨域访问控件与WebService的资料整理