【传送门:BZOJ4259&BZOJ4503


简要题意:

  给出两个字符串,第一个串长度为m,第二个串长度为n,字符串中如果有*字符,则代表当前位置可以匹配任何字符

  求出第一个字符串在第二个字串中出现的次数,及出现的位置开头在第二个字符串的位置(从小到大输出)


题解:

  FFT,通配符匹配

  两道题几乎没区别

  对于两个串长度为i,它们的相似程度为$\sum_{j=0}^{i-1}(A[j]-B[j])^2$(A[j]!='*'&&B[j]!='*')

  把*设为0,则得到$\sum_{j=0}^{i-1}(A[j]-B[j])^2A[j]B[j]$

  显然只有当$\sum_{j=0}^{i-1}(A[j]-B[j])^2A[j]B[j]$为0时,A串和B串才能完全匹配

  那么对于这道题而言,设f(i)为以B的i位置为结尾的长度为n的子串与A串的相似程度

  先将n--,m--(方便写公式),然后在A后面补0

  显然$f(i)=\sum_{j=0}^{m}(A[j]-B[i-m+j])^2A[j]B[i-m+j]$

  我们把A数组翻转,就会得到$f(i)=\sum_{j=0}^{i}(A[j]-B[i-j])^2A[j]B[i-j]$

  然后把这个式子拆开就得到$f(i)=\sum_{j=0}^{i}A[j]^3B[i-j]-2*\sum_{j=0}^{i}A[j]^2B[i-j]^2+\sum_{j=0}^{i}A[j]*B[i-j]^3$

  皆大欢喜,直接三次FFT分别求就可以了


参考代码(一):

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<algorithm>
  5. #include<cmath>
  6. using namespace std;
  7. typedef long long LL;
  8. const double PI=acos(-1.0);
  9. struct Complex
  10. {
  11. double r,i;
  12. Complex(){}
  13. Complex(double _r,double _i){r=_r;i=_i;}
  14. friend Complex operator + (const Complex &x,const Complex &y){return Complex(x.r+y.r,x.i+y.i);}
  15. friend Complex operator - (const Complex &x,const Complex &y){return Complex(x.r-y.r,x.i-y.i);}
  16. friend Complex operator * (const Complex &x,const Complex &y){return Complex(x.r*y.r-x.i*y.i,x.r*y.i+x.i*y.r);}
  17. }a[],b[];
  18. int R[];
  19. void fft(Complex *y,int len,int on)
  20. {
  21. for(int i=;i<len;i++) if(i<R[i]) swap(y[i],y[R[i]]);
  22. for(int i=;i<len;i<<=)
  23. {
  24. Complex wn(cos(PI/i),sin(on*PI/i));
  25. for(int j=;j<len;j+=(i<<))
  26. {
  27. Complex w(,);
  28. for(int k=;k<i;k++,w=w*wn)
  29. {
  30. Complex u=y[j+k];
  31. Complex v=w*y[j+k+i];
  32. y[j+k]=u+v;
  33. y[j+k+i]=u-v;
  34. }
  35. }
  36. }
  37. if(on==-) for(int i=;i<=len;i++) y[i].r/=len;
  38. }
  39. void calc(int n,int m)
  40. {
  41. int L=;m+=n;
  42. for(n=;n<=m;n<<=) L++;
  43. memset(R,,sizeof(R));
  44. for(int i=;i<n;i++) R[i]=(R[i>>]>>)|(i&)<<(L-);
  45. fft(a,n,);fft(b,n,);
  46. for(int i=;i<=n;i++) a[i]=a[i]*b[i];
  47. fft(a,n,-);
  48. }
  49. char s1[],s2[];
  50. int A[],B[];
  51. int q[];
  52. double f[];
  53. int main()
  54. {
  55. int n,m;
  56. scanf("%d%d",&n,&m);n--;m--;
  57. scanf("%s%s",s1,s2);
  58. for(int i=;i<=n;i++)
  59. {
  60. if(s1[n-i]=='*') A[i]=;
  61. else A[i]=s1[n-i]-'a'+;
  62. }
  63. for(int i=;i<=m;i++)
  64. {
  65. if(s2[i]=='*') B[i]=;
  66. else B[i]=s2[i]-'a'+;
  67. }
  68. memset(f,,sizeof(f));
  69. for(int i=;i<=n;i++) a[i].r=A[i]*A[i]*A[i];
  70. for(int i=;i<=m;i++) b[i].r=B[i];
  71. calc(n,m);
  72. for(int i=;i<=m;i++) f[i]+=a[i].r;
  73. memset(a,,sizeof(a));
  74. memset(b,,sizeof(b));
  75. for(int i=;i<=n;i++) a[i].r=A[i]*A[i];
  76. for(int i=;i<=m;i++) b[i].r=B[i]*B[i];
  77. calc(n,m);
  78. for(int i=;i<=m;i++) f[i]-=2.0*a[i].r;
  79. memset(a,,sizeof(a));
  80. memset(b,,sizeof(b));
  81. for(int i=;i<=n;i++) a[i].r=A[i];
  82. for(int i=;i<=m;i++) b[i].r=B[i]*B[i]*B[i];
  83. calc(n,m);
  84. for(int i=;i<=m;i++) f[i]+=a[i].r;
  85. int cnt=;
  86. for(int i=n;i<=m;i++) if(f[i]<0.5) q[++cnt]=i-n;
  87. printf("%d\n",cnt);
  88. if(cnt>)
  89. {
  90. for(int i=;i<cnt;i++) printf("%d ",q[i]+);
  91. printf("%d\n",q[cnt]+);
  92. }
  93. return ;
  94. }

参考代码(二):

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<cstdlib>
  4. #include<algorithm>
  5. #include<cmath>
  6. using namespace std;
  7. typedef long long LL;
  8. const double PI=acos(-1.0);
  9. struct Complex
  10. {
  11. double r,i;
  12. Complex(){}
  13. Complex(double _r,double _i){r=_r;i=_i;}
  14. friend Complex operator + (const Complex &x,const Complex &y){return Complex(x.r+y.r,x.i+y.i);}
  15. friend Complex operator - (const Complex &x,const Complex &y){return Complex(x.r-y.r,x.i-y.i);}
  16. friend Complex operator * (const Complex &x,const Complex &y){return Complex(x.r*y.r-x.i*y.i,x.r*y.i+x.i*y.r);}
  17. }a[],b[];
  18. int R[];
  19. void fft(Complex *y,int len,int on)
  20. {
  21. for(int i=;i<len;i++) if(i<R[i]) swap(y[i],y[R[i]]);
  22. for(int i=;i<len;i<<=)
  23. {
  24. Complex wn(cos(PI/i),sin(on*PI/i));
  25. for(int j=;j<len;j+=(i<<))
  26. {
  27. Complex w(,);
  28. for(int k=;k<i;k++,w=w*wn)
  29. {
  30. Complex u=y[j+k];
  31. Complex v=w*y[j+k+i];
  32. y[j+k]=u+v;
  33. y[j+k+i]=u-v;
  34. }
  35. }
  36. }
  37. if(on==-) for(int i=;i<=len;i++) y[i].r/=len;
  38. }
  39. void calc(int n,int m)
  40. {
  41. int L=;m+=n;
  42. for(n=;n<=m;n<<=) L++;
  43. memset(R,,sizeof(R));
  44. for(int i=;i<n;i++) R[i]=(R[i>>]>>)|(i&)<<(L-);
  45. fft(a,n,);fft(b,n,);
  46. for(int i=;i<=n;i++) a[i]=a[i]*b[i];
  47. fft(a,n,-);
  48. }
  49. char s1[],s2[];
  50. int A[],B[];
  51. int q[];
  52. double f[];
  53. int main()
  54. {
  55. int m,n;
  56. scanf("%s%s",s1,s2);
  57. m=strlen(s1);n=strlen(s2);
  58. m--;n--;
  59. for(int i=;i<=m;i++) B[i]=s1[i]-'a'+;
  60. for(int i=;i<=n;i++)
  61. {
  62. if(s2[n-i]=='?') A[i]=;
  63. else A[i]=s2[n-i]-'a'+;
  64. }
  65. memset(f,,sizeof(f));
  66. for(int i=;i<=n;i++) a[i].r=A[i]*A[i]*A[i];
  67. for(int i=;i<=m;i++) b[i].r=B[i];
  68. calc(n,m);
  69. for(int i=;i<=m;i++) f[i]+=a[i].r;
  70. memset(a,,sizeof(a));
  71. memset(b,,sizeof(b));
  72. for(int i=;i<=n;i++) a[i].r=A[i]*A[i];
  73. for(int i=;i<=m;i++) b[i].r=B[i]*B[i];
  74. calc(n,m);
  75. for(int i=;i<=m;i++) f[i]-=2.0*a[i].r;
  76. memset(a,,sizeof(a));
  77. memset(b,,sizeof(b));
  78. for(int i=;i<=n;i++) a[i].r=A[i];
  79. for(int i=;i<=m;i++) b[i].r=B[i]*B[i]*B[i];
  80. calc(n,m);
  81. for(int i=;i<=m;i++) f[i]+=a[i].r;
  82. int cnt=;
  83. for(int i=n;i<=m;i++) if(f[i]<0.5) q[++cnt]=i-n;
  84. printf("%d\n",cnt);
  85. if(cnt>) for(int i=;i<=cnt;i++) printf("%d\n",q[i]);
  86. return ;
  87. }

BZOJ4259: 残缺的字符串 & BZOJ4503: 两个串的更多相关文章

  1. bzoj4503: 两个串 bitset

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

  2. BZOJ4259残缺的字符串

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

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

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

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

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

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

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

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

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

  7. BZOJ4503: 两个串

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

  8. BZOJ4503 两个串 【fft】

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

  9. BZOJ4503 两个串 多项式 FFT

    题目传送门 - BZOJ4503 题意概括 给定两个字符串S和T,回答T在S中出现了几次,在哪些位置出现.注意T中可能有?字符,可以匹配任何字符. 题解 首先,假装你已经知道了这是一道$FFT$题. ...

随机推荐

  1. ASP.NET-权限管理五张表

    ASP.NET 权限管理五张表 权限管理的表(5张表) 每个表里面必有的一些信息 序号 名称  字段  类型   主键 默认值 是否为空 备注 1  用户ID  ID      INT     是   ...

  2. atitit。流程图的设计与制作&#160;attilax&#160;总结

    atitit.流程图的设计与制作 attilax 总结 1. 流程图的规范1 2. 画图语言2 2.1. atitit.CSDN-markdown编辑器2 2.2. js-sequence-diagr ...

  3. HDU 5228 ZCC loves straight flush( BestCoder Round #41)

    题目链接:pid=5228">ZCC loves straight flush pid=5228">题面: pid=5228"> ZCC loves s ...

  4. bzoj1045: [HAOI2008] 糖果传递(数论)

    1045: [HAOI2008] 糖果传递 题目:传送门(双倍经验3293) 题解: 一开始想着DP贪心一顿乱搞,结果就GG了 十分感谢hzwer大佬写的毒瘤数论题解: 首先,最终每个小朋友的糖果数量 ...

  5. 安卓 使用Gradle生成正式签名apk文件

    1. 进入app中的build.gradle下面进行配置 2.进入Gradle下面选择clean和assembleRelese,双击 3.生成成功,前往查看 4.加密更安全

  6. Laravel-redis-订阅发布

    Laravel-redis-订阅发布 标签(空格分隔): php Redis订阅发布 理解订阅发布: publish:将信息 message 发送到指定的频道 channel publish test ...

  7. 【DNN 系列 创建WEB模块 项目】

    现在DNN已经更新到8.0.3 然而使用7.0 的项目模块 会报错, 就是填写网站的时候 会再网站的项目当中添加文件夹这样会破坏网站 所以来自己创建自己的模板项目 首选创建空的WEB 项目网站 创建完 ...

  8. 【记录】Linux安装JDK详细步骤

    Linux安装JDK步骤1. 先从网上下载jdk(jdk-1_5_0_02-linux-i586.rpm) ,推荐SUN的官方网站www.sun.com,下载后放在/home目录中,当然其它地方也行. ...

  9. 理解 this.initialize.apply ( this, arguments )定义对象的一种方式

    var Class = { create:function() { return function() { this.initialize.apply(this, arguments); }; } } ...

  10. HDU 1087 Super Jumping! Jumping! Jumping!【DP】

    解题思路:题目的大意是给出一列数,求这列数里面最长递增数列的和 dp[i]表示到达地点i的最大值,那么是如何达到i的呢,则我们可以考虑没有限制条件时候的跳跃,即可以从第1,2,3,---,i-1个地点 ...