zoukankan      html  css  js  c++  java
  • CF528D Fuzzy Search 字符串匹配+FFT

    题意:

      DNA序列,在母串s中匹配模式串t,对于s中每个位置i,只要s[i-k]到s[i+k]中有c就认为匹配了c。求有多少个位置匹配了t。

    分析:

      这个字符串匹配的方式,什么kmp,各种自动机都不灵。

      所以有一个邪门功夫,fft字符串匹配。(做过洛谷《残缺的字符串》一题的应该都不陌生,带通配符的匹配字符串可以用fft卷积来做)

      首先,由于字符集大小只有4,所以我们可以对每个字符分别考虑。

      根据题意,对于每个字符,我们预处理a[i]数组,代表i位置是否能匹配当前字符(左右k个能匹配也算)

      之后b[i]数组,保存t[i]位置的字符是不是c。

      然后将b数组倒过来,fft做一下卷积,把答案累计起来检查总和是不是m就可以判断是否匹配。

    代码:

     1 #include<bits/stdc++.h>
     2 #define db double
     3 #define cp complex<db>
     4 using namespace std;
     5 const int N=530005;
     6 const db pi=acos(-1);
     7 int ans,ton[N],n,m,k,lm,L,r[N];
     8 char s[N],t[N];cp a[N],b[N];
     9 void init(){
    10     scanf("%d%d%d%s%s",&n,&m,&k,s,t);
    11 } void fft(cp *f,int op){
    12     for(int i=0;i<lm;i++)
    13     if(i>r[i]) swap(f[i],f[r[i]]);
    14     for(int l=1;l<lm;l<<=1){
    15         cp wn(cos(pi/l),op*sin(pi/l));
    16         for(int i=0;i<lm;i+=(l<<1)){
    17             cp w(1,0);
    18             for(int j=0;j<l;j++,w*=wn){
    19                 cp T=w*f[i+j+l];
    20                 f[i+j+l]=f[i+j]-T;f[i+j]+=T;
    21             }
    22         } 
    23     } if(op==-1) for(int i=0;i<lm;i++) f[i]/=lm;
    24 } void calc(char c){
    25     memset(a,0,sizeof(a));memset(b,0,sizeof(b));
    26     int cnt=0;
    27     for(int i=0;i<k;i++) cnt+=(s[i]==c);
    28     for(int i=0;i<n;i++){
    29         if(i+k<n) cnt+=(s[i+k]==c);
    30         if(i-k-1>=0) cnt-=(s[i-k-1]==c);
    31         a[i]=cnt>0?1:0;cout<<a[i]<<" ";
    32     } for(int i=0;i<m;i++) b[i]=(t[i]==c);puts("");
    33     fft(a,1);fft(b,1);
    34     for(int i=0;i<lm;i++) a[i]*=b[i];
    35     fft(a,-1);for(int i=0;i<=n-m;i++)
    36     ton[i]+=(int)(a[i+m-1].real()+0.5);
    37 } void solve(){
    38     for(lm=1;lm<=n+m-2;lm<<=1,L++);
    39     for(int i=0;i<lm;i++)
    40     r[i]=(r[i>>1]>>1)|((i&1)<<(L-1));
    41     reverse(t,t+m);calc('A');
    42     calc('G');calc('C');calc('T');
    43     for(int i=0;i<=n-m;i++) if(ton[i]==m) ans++;
    44     printf("%d
    ",ans);
    45 } int main(){
    46     init();solve();return 0;
    47 }
    fft字符串匹配
  • 相关阅读:
    数组的练习
    java基础类和对象
    字符串的练习
    二分查找算法
    Python-charle+fiddler
    python-week1-postman+jemter-soapUI
    OBB盒的实现
    Bounding volume
    OSG动画学习
    OSG 自定义数据类型 关键帧动画
  • 原文地址:https://www.cnblogs.com/Alan-Luo/p/10422171.html
Copyright © 2011-2022 走看看