日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CF528D. Fuzzy Search [FFT]

發布時間:2023/12/10 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CF528D. Fuzzy Search [FFT] 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

CF528D. Fuzzy Search

題意:DNA序列,在母串s中匹配模式串t,對于s中每個位置i,只要s[i-k]到s[i+k]中有c就認為匹配了c。求有多少個位置匹配了t


預處理\(f[i][j]\)表示位置i可以匹配字符j
分別考慮每一個字符c,對s的每個位置i求出用\(s[i,i+m-1]\)匹配t,這個字符匹配了幾次
\(a_i=[s的位置i匹配c],\ b_i=[t_i=c]\)
那么c的匹配次數就是\(c_j=\sum\limits_{i=0}^{m-1}a_{j+i}b_i\),位置i匹配了t當且僅當四種字符的匹配次數和等于t的長度m


這時候就可以考慮bitset暴力過了

一個常用技巧是,反轉模式串(或母串),然后就成了卷積的形式:
\[ c_j=\sum\limits_{i=0}^{m-1}a_{j+i}b_{m-1-i}=D_{m+j-1} \]
這樣計算是沒有問題的,因為b只有\([0,m-1]\)有值其他地方為0

注意處理每個字符前memset a和b!!!!!

#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; typedef long long ll; const int N=(1<<20)+5, INF=1e9; const double PI=acos(-1); inline int read(){char c=getchar();int x=0,f=1;while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}return x*f; }struct meow{double x, y;meow(double a=0, double b=0):x(a), y(b){} }; meow operator +(meow a, meow b) {return meow(a.x+b.x, a.y+b.y);} meow operator -(meow a, meow b) {return meow(a.x-b.x, a.y-b.y);} meow operator *(meow a, meow b) {return meow(a.x*b.x-a.y*b.y, a.x*b.y+a.y*b.x);} meow conj(meow a) {return meow(a.x, -a.y);} typedef meow cd;namespace FFT{int n, rev[N];void ini(int lim) {n=1; int k=0;while(n<lim) n<<=1, k++;for(int i=0; i<n; i++) rev[i] = (rev[i>>1]>>1) | ((i&1)<<(k-1));}void dft(cd *a, int flag) {for(int i=0; i<n; i++) if(i<rev[i]) swap(a[i], a[rev[i]]);for(int l=2; l<=n; l<<=1) {int m=l>>1; cd wn = meow(cos(2*PI/l), flag*sin(2*PI/l));for(cd *p=a; p!=a+n; p+=l) {cd w(1, 0);for(int k=0; k<m; k++) {cd t = w*p[k+m];p[k+m] = p[k] - t;p[k] = p[k] + t;w=w*wn;}}}if(flag==-1) for(int i=0; i<n; i++) a[i].x/=n;}void mul(cd *a, cd *b) {dft(a, 1); dft(b, 1);for(int i=0; i<n; i++) a[i]=a[i]*b[i];dft(a, -1);} }using FFT::mul; using FFT::ini;int n, m, k, lim, f[N][5], cnt[5], id[300]; cd a[N], b[N], c[N]; char s[N], t[N]; int ans[N]; void solve(int now) { memset(a, 0, sizeof(a)); memset(b, 0, sizeof(b));for(int i=0; i<n; i++) a[i].x = f[i][now];for(int i=0; i<m; i++) b[m-1-i].x = id[(int)t[i]]==now; mul(a, b);for(int i=0; i<n; i++) ans[i] += int(a[m-1+i].x+0.5); } int main() {freopen("in","r",stdin);n=read(); m=read(); k=read(); lim=n+m-1; ini(lim);scanf("%s%s",s,t);id['A']=0; id['T']=1; id['C']=2; id['G']=3;int l=0, r=0; cnt[ id[(int)s[0]] ]++;for(int i=0; i<n; i++) {while(l<i-k) cnt[ id[(int)s[l++]] ]--;while(r<n-1 && r<i+k) cnt[ id[(int)s[++r]] ]++;for(int j=0; j<4; j++) if(cnt[j]) f[i][j]=1;}for(int i=0; i<4; i++) solve(i);int sum=0;for(int i=0; i<n; i++) if(ans[i]==m) sum++;printf("%d",sum); }

總結

以上是生活随笔為你收集整理的CF528D. Fuzzy Search [FFT]的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。