[关闭]
@ysner 2018-09-19T22:02:35.000000Z 字数 2175 阅读 2150

[CF528D]Fuzzy Search

字符串 FFT/NTT


题面

给定原串和匹配串,允许错开不超过位匹配(即中第位字符可以与中的相同字符匹配)。问中出现次数。
字符集大小为

解析

在字符串问题上,都有一个通往卷积的套路:把某个字符串翻转。
这样可以使得两个字符串中,当前对应的字符坐标和均为,满足卷积形式。
对每个字符串分开考虑,设两个多项式:(其中表示当前枚举的字符)



两个多项式卷一下,就是这种字符在中第个位置上的匹配数。
最后,如果有位置个字符匹配数之和达到,就说明形成了一种匹配方案。

其实这个玩意儿不太好理解。
中第位为中第位为,则两项相乘将贡献答案,放在位。
同样放在这一位的答案,只有可能是形成的。
而这样的过程对应的是串的匹配过程(翻转后)。

还有有人跟我说形成方案的位数(即)小于。。。我不能理解。。。

注意字符串起点位置必须是!!!

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cmath>
  4. #include<cstdio>
  5. #include<cstdlib>
  6. #include<algorithm>
  7. #define ll long long
  8. #define re register
  9. #define il inline
  10. #define cp complex
  11. #define db double
  12. #define fp(i,a,b) for(re int i=a;i<=b;i++)
  13. #define fq(i,a,b) for(re int i=a;i>=b;i--)
  14. using namespace std;
  15. const int N=8e5+100;
  16. const db pi=acos(-1);
  17. int n,m,k,l,r[N],lim=1,ans[N/4],Ans;
  18. char s1[N/4],s2[N/4],id[4]={'A','C','G','T'};
  19. struct cp
  20. {
  21. db x,y;
  22. il cp(){x=y=0;}
  23. il cp(re db xx,re db yy){x=xx,y=yy;}
  24. }a[N],b[N];
  25. il cp operator + (re cp a,re cp b){return cp(a.x+b.x,a.y+b.y);}
  26. il cp operator - (re cp a,re cp b){return cp(a.x-b.x,a.y-b.y);}
  27. il cp operator * (re cp a,re cp b){return cp(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
  28. il void FFT(re cp *A,re int tp)
  29. {
  30. fp(i,1,lim-1) if(i<r[i]) swap(A[i],A[r[i]]);
  31. for(re int mid=1;mid<lim;mid<<=1)
  32. {
  33. re cp W(cos(pi/mid),tp*sin(pi/mid));
  34. for(re int R=mid<<1,j=0;j<lim;j+=R)
  35. {
  36. re cp w(1,0);
  37. for(re int k=0;k<mid;++k,w=w*W)
  38. {
  39. re cp x=A[j+k],y=w*A[j+mid+k];
  40. A[j+k]=x+y;A[j+mid+k]=x-y;
  41. }
  42. }
  43. }
  44. }
  45. il ll gi()
  46. {
  47. re ll x=0,t=1;
  48. re char ch=getchar();
  49. while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
  50. if(ch=='-') t=-1,ch=getchar();
  51. while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
  52. return x*t;
  53. }
  54. int main()
  55. {
  56. n=gi();m=gi();k=gi();
  57. scanf("%s",s1);scanf("%s",s2);reverse(s2,s2+m);
  58. while(lim<=n+m) lim<<=1,++l;
  59. fp(i,1,lim-1) r[i]=(r[i>>1]>>1)|((i&1)<<l-1);
  60. fp(o,0,3)
  61. {
  62. fp(i,0,lim-1) a[i].x=a[i].y=b[i].x=b[i].y=0;
  63. re int pos=-1e9;
  64. fp(i,0,n-1)
  65. {
  66. if(s1[i]==id[o]) pos=i;
  67. if(pos>=i-k) a[i].x=1;
  68. }
  69. pos=1e9;
  70. fq(i,n-1,0)
  71. {
  72. if(s1[i]==id[o]) pos=i;
  73. if(pos<=i+k) a[i].x=1;
  74. }
  75. fp(i,0,m-1) if(s2[i]==id[o]) b[i].x=1;
  76. FFT(a,1);FFT(b,1);
  77. fp(i,0,lim-1) a[i]=a[i]*b[i];
  78. FFT(a,-1);
  79. fp(i,0,lim-1) ans[i]+=(int)(a[i].x/lim+0.5);
  80. }
  81. fp(i,0,lim-1) if(ans[i]==m) ++Ans;
  82. printf("%d\n",Ans);
  83. return 0;
  84. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注