1. 程式人生 > >CF528D Fuzzy Search (生成函數+FFT)

CF528D Fuzzy Search (生成函數+FFT)

lin namespace mil lan i++ 生成函數 ont end sea

題目傳送門

題目大意:給你兩個只包含A,G,C,T的字符串$S$,$T$,$S$長$T$短,按照如下圖方式匹配 解釋不明白直接上圖

技術分享圖片

能容錯的距離不超過$K$,求能$T$被匹配上的次數

$S$串同一個位置可以被$T$的不同位置匹配多次

對4種字符分別處理,假設我們現在只討論字符A

對於字符串AGCAATTCAT,字符A的生成函數就是1001100010

題目要求距離不超過K就能匹配,把周圍距離不超過$K$的位置都變成1,形成一個新串$S‘$

$S$ 1001100010

$S‘$ 1111110111

只要$T$和$S‘$的某個子串匹配時,子串中1的個數 不少於 $T$串中1的個數,就表明$T$串能被匹配上

把$T$串反轉,再進行卷積,每一位都分4鐘情況討論即可

  1 #include <cmath>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #define N1 (1<<19)
  6 #define il inline
  7 #define dd double
  8 #define ld long double
  9 #define ll long long
 10 using namespace
std; 11 12 int gint() 13 { 14 int ret=0,fh=1;char c=getchar(); 15 while(c<0||c>9){if(c==-)fh=-1;c=getchar();} 16 while(c>=0&&c<=9){ret=ret*10+c-0;c=getchar();} 17 return ret*fh; 18 } 19 int idx(char c) 20 { 21 if(c==A) return 0;
22 if(c==C) return 1; 23 if(c==G) return 2; 24 if(c==T) return 3; 25 } 26 const int inf=0x3f3f3f3f; 27 28 namespace FFT{ 29 30 const dd pi=acos(-1); 31 struct cp{ 32 dd x,y; 33 friend cp operator + (const cp &s1,const cp &s2){ return (cp){s1.x+s2.x,s1.y+s2.y}; } 34 friend cp operator - (const cp &s1,const cp &s2){ return (cp){s1.x-s2.x,s1.y-s2.y}; } 35 friend cp operator * (const cp &s1,const cp &s2){ return (cp){s1.x*s2.x-s1.y*s2.y,s1.y*s2.x+s1.x*s2.y}; } 36 }a[N1],b[N1],c[N1]; 37 int r[N1]; 38 void FFT(cp *s,int len,int type) 39 { 40 int i,j,k; cp wn,w,t; 41 for(i=0;i<len;i++) if(i<r[i]) swap(s[i],s[r[i]]); 42 for(k=2;k<=len;k<<=1) 43 { 44 wn=(cp){cos(2.0*type*pi/k),sin(2.0*type*pi/k)}; 45 for(i=0;i<len;i+=k) 46 { 47 w=(cp){1,0}; 48 for(j=0;j<(k>>1);j++,w=w*wn) 49 { 50 t=w*s[i+j+(k>>1)]; 51 s[i+j+(k>>1)]=s[i+j]-t; 52 s[i+j]=s[i+j]+t; 53 } 54 } 55 } 56 } 57 void Main(int len,int L) 58 { 59 int i; 60 for(i=0;i<len;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(L-1)); 61 FFT(a,len,1); FFT(b,len,1); 62 for(i=0;i<len;i++) c[i]=a[i]*b[i]; 63 FFT(c,len,-1); 64 for(i=0;i<len;i++) c[i].x/=len; 65 } 66 void init() 67 { 68 memset(a,0,sizeof(a)); 69 memset(b,0,sizeof(b)); 70 } 71 72 }; 73 using FFT::a; using FFT::b; using FFT::c; 74 75 int s[N1],t[N1],nt[N1],n,m,K,len,L; 76 char S[N1],T[N1]; 77 void solve(int p) 78 { 79 FFT::init(); 80 int i,j,k,num=0; 81 for(i=0,k=0;i<n;i++) if(s[i]==p) 82 for(k=max(k,i-K);k<=min(n,i+K);k++) a[k].x=1; 83 for(i=n-1,k=n-1;i;i--) if(s[i]==p) 84 for(k=min(k,i+K);k>=max(0,i-K);k--) a[k].x=1; 85 for(i=0;i<m;i++) if(t[i]==p) b[m-i-1].x=1,num++; 86 FFT::Main(len,L); 87 for(i=0;i<n;i++) if((int)(c[i].x+0.1)<num) nt[i]=1; 88 } 89 90 int main() 91 { 92 int i,j,ans=0; 93 scanf("%d%d%d",&n,&m,&K); 94 scanf("%s",S); scanf("%s",T); 95 for(i=0;i<n;i++) s[i]=idx(S[i]); 96 for(i=0;i<m;i++) t[i]=idx(T[i]); 97 for(len=1,L=0;len<(n+m-1);len<<=1,L++); 98 solve(0); 99 solve(1); 100 solve(2); 101 solve(3); 102 for(i=0;i<n;i++) if(!nt[i]) ans++; 103 printf("%d\n",ans); 104 return 0; 105 106 }

CF528D Fuzzy Search (生成函數+FFT)