B - Fuzzy Search (FFT)

题目链接:https://cn.vjudge.net/contest/281959#problem/B

题目大意:给你n,m,k。然后输入两个字符串,n代表第一个字符串s1,m代表第二个字符串s2,然后问你第二个字符串在第一个字符串能匹配的次数(选定第一个字符串的位置之后,任意s2中一个字符串,都能在s1对应的位置左右k个都能找到相同的字符)。

具体思路:和 这一篇的思路基本使用一样的。

AC代码:

  1 #include<iostream>
  2 #include<cstring>
  3 #include<string>
  4 #include<cmath>
  5 #include<algorithm>
  6 #include<stdio.h>
  7 using namespace std;
  8 # define ll long long
  9 const double PI = acos(-1.0);
 10 const int maxn = 8e5+100;
 11 struct complex
 12 {
 13     double r,i;
 14     complex(double _r = 0,double _i = 0)
 15     {
 16         r = _r;
 17         i = _i;
 18     }
 19     complex operator +(const complex &b)
 20     {
 21         return complex(r+b.r,i+b.i);
 22     }
 23     complex operator -(const complex &b)
 24     {
 25         return complex(r-b.r,i-b.i);
 26     }
 27     complex operator *(const complex &b)
 28     {
 29         return complex(r*b.r-i*b.i,r*b.i+i*b.r);
 30     }
 31 };
 32 void change(complex y[],int len)
 33 {
 34     int i,j,k;
 35     for(i = 1, j = len/2; i < len-1; i++)
 36     {
 37         if(i < j)
 38             swap(y[i],y[j]);
 39         k = len/2;
 40         while( j >= k)
 41         {
 42             j -= k;
 43             k /= 2;
 44         }
 45         if(j < k)
 46             j += k;
 47     }
 48 }
 49 void fft(complex y[],int len,int on)
 50 {
 51     change(y,len);
 52     for(int h = 2; h <= len; h <<= 1)
 53     {
 54         complex wn(cos(-on*2*PI/h),sin(-on*2*PI/h));
 55         for(int j = 0; j < len; j += h)
 56         {
 57             complex w(1,0);
 58             for(int k = j; k < j+h/2; k++)
 59             {
 60                 complex u = y[k];
 61                 complex t = w*y[k+h/2];
 62                 y[k] = u+t;
 63                 y[k+h/2] = u-t;
 64                 w = w*wn;
 65             }
 66         }
 67     }
 68     if(on == -1)
 69         for(int i = 0; i < len; i++)
 70             y[i].r /= len;
 71 }
 72 char str1[maxn],str2[maxn];
 73 complex x1[maxn],x2[maxn];
 74 int len1,len2,len=1;
 75 int vis[maxn][5],id[maxn],cnt[10];
 76 ll ans[maxn];
 77 int main()
 78 {
 79     int n,m,k;
 80     scanf("%d %d %d",&n,&m,&k);
 81     scanf("%s",str1+1);
 82     scanf("%s",str2+1);
 83     len1=strlen(str1+1);
 84     len2=strlen(str2+1);
 85     while(len<len1*2||len<len2*2)
 86         len<<=1;
 87    //     cout<<len<<endl;
 88     int l=0,r=0;
 89     id[‘A‘]=1,id[‘G‘]=2,id[‘T‘]=3,id[‘C‘]=4;
 90     for(int i=1; i<=n; i++)
 91     {
 92         while(l<n&&l<i-k)//判断这个区间内的字符。
 93             cnt[id[(int)str1[l++]]]--;
 94         while(r<n&&r<i+k)
 95             cnt[id[(int)str1[++r]]]++;
 96         for(int j=1; j<=4; j++)
 97             if(cnt[j])
 98                 vis[i][j]=1;
 99     }
100     for(int i=1; i<=4; i++)
101     {
102         for(int j=0; j<len; j++)
103         {
104             x1[j]=complex(0,0);
105             x2[j]=complex(0,0);
106         }
107         for(int j=1; j<=n; j++)
108         {
109             if(vis[j][i])
110                 x1[j-1]=complex(1,0);
111         }
112         for(int j=1; j<=m; j++)
113         {
114             if(id[(int)str2[j]]==i)
115                 x2[m-j]=complex(1,0);
116         }
117         fft(x1,len,1);
118         fft(x2,len,1);
119         for(int j=0; j<len; j++)
120         {
121             x1[j]=x1[j]*x2[j];
122         }
123         fft(x1,len,-1);
124         for(int j=0; j<len; j++)
125         {
126             ans[j]+=(ll)(x1[j].r+0.5);
127         }
128     }
129     int num=0;
130     for(int i=0; i<len; i++)
131     {
132     //    cout<<i<<" "<<ans[i]<<endl;
133         if(ans[i]==m)
134             num++;
135     }
136     printf("%d\n",num);
137     return 0;
138 }

原文地址:https://www.cnblogs.com/letlifestop/p/10349909.html

时间: 2024-10-06 13:12:11

B - Fuzzy Search (FFT)的相关文章

Codeforces 528D Fuzzy Search(FFT)

题目 Source http://codeforces.com/problemset/problem/528/D Description Leonid works for a small and promising start-up that works on decoding the human genome. His duties include solving complex problems of finding certain patterns in long strings cons

快速傅里叶变换(FFT)

快速傅里叶变换(FFT)算法[详解] 快速傅里叶变换(Fast Fourier Transform)是信号处理与数据分析领域里最重要的算法之一.我打开一本老旧的算法书,欣赏了JW Cooley 和 John Tukey 在1965年的文章中,以看似简单的计算技巧来讲解这个东西. 本文的目标是,深入Cooley-Tukey  FFT 算法,解释作为其根源的"对称性",并以一些直观的python代码将其理论转变为实际.我希望这次研究能对这个算法的背景原理有更全面的认识. FFT(快速傅里叶

Hdu 1402 (FFT)

题目链接 A * B Problem Plus Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 12490    Accepted Submission(s): 2206 Problem Description Calculate A * B. Input Each line will contain two integers A and

洛谷P3803 【模板】多项式乘法(FFT)

P3803 [模板]多项式乘法(FFT) 题目背景 这是一道FFT模板题 题目描述 给定一个n次多项式F(x),和一个m次多项式G(x). 请求出F(x)和G(x)的卷积. 输入输出格式 输入格式: 第一行2个正整数n,m. 接下来一行n+1个数字,从低到高表示F(x)的系数. 接下来一行m+1个数字,从低到高表示G(x))的系数. 输出格式: 一行n+m+1个数字,从低到高表示F(x)∗G(x)的系数. 输入输出样例 输入样例#1: 复制 1 2 1 2 1 2 1 输出样例#1: 复制 1

BZOJ[3527],[ZJOI2014]力(FFT)

BZOJ[3527],[ZJOI2014]力(FFT) 题意: 给出\(n\)个数\(q_i\),给出\(Fj\)的定义如下: \(F_j=\sum \limits _ {i < j} \frac{q_iq_j}{(i-j)^2}-\sum \limits _{i >j} \frac{q_iq_j}{(i-j)^2}.\) 令\(E_i=F_i/q_i\),求\(E_i\). 题解: 一开始没发现求\(E_i\)... 其实题目还更容易想了... \(E_i=\sum\limits _{j&l

【知识总结】快速傅里叶变换(FFT)

这可能是我第五次学FFT了--菜哭qwq 先给出一些个人认为非常优秀的参考资料: 一小时学会快速傅里叶变换(Fast Fourier Transform) - 知乎 小学生都能看懂的FFT!!! - 胡小兔 - 博客园 快速傅里叶变换(FFT)用于计算两个\(n\)次多项式相乘,能把复杂度从朴素的\(O(n^2)\)优化到\(O(nlog_2n)\).一个常见的应用是计算大整数相乘. 本文中所有多项式默认\(x\)为变量,其他字母均为常数.所有角均为弧度制. 一.多项式的两种表示方法 我们平时常

HDU 4609 3-idiots(FFT)

题意:给出n个正整数(数组A).每次随机选出三个数.问这三个数能组成三角形的概率为多大? 首先,我们用类似桶排计数的方法作出两个数组a,b,储存每个长度有几条边,然后对两个数组求卷积. 求出卷积后,这就代表了2条边能构成的边长度的集合了,注意,由于求卷积的时候可能把两条相同的边相加,所以最后求出的数组一定要减去这重复的部分,然后,先算x后算y等价于先算y后算x,所以要除以二. 然后,对于第三条边a[i],我们这样考虑:令它作为这三条边中最大的那条! 所以之前的卷积求出来的两边和一定会比这条边大,

傅里叶变换(FFT)的多相滤波结构实现

作者:桂. 时间:2017-09-25  14:53:01 链接:http://www.cnblogs.com/xingshansi/p/7591868.html 前言 以前在梳理信号频域变换的时候,提到逆序级联FFT(Inverse cascade FFT)的实现思路,后来分析多相滤波信道化,才发现其实Cascade FFT就是FFT的多相结构实现,在此系统梳理一下. 一.多相结构FFT实现 A-传统测频技术分析 信号的短时傅里叶变换(STFT)可表示为: 其中s为输入信号,w为对应窗函数.长

【ZOJ 3856】Goldbach(FFT)

题意:最多使用三个质数做加法和乘法,问得到X有多少种方案. 这道题的话分几种情况讨论清楚就好了. 1.只有一个数的情况,如果这个数是质数则方案数加1 2.有两个数的情况,可以将两个数做加法和乘法,加法的话将质数得到的数字做一遍FFT,乘法直接做sqrt(n) * sqrt(n)就好了 3.有三个数的情况,分别有三种方法,分别是a + b + c, a + b * c,a * b * c 对于a * b * c,暴力遍历一遍就好,对于a + b * c,首先暴力遍历下b * c,然后再将一个数的两