CF528D Fuzzy Search (生成函數+FFT)
阿新 • • 發佈:2019-02-06
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 namespacestd; 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)