题意:求母串中可以匹配模式串的子串的个数,但是每一位i的字符可以左右偏移k个位置.

分析:类似于 UVALive -4671. 用FFT求出每个字符成功匹配的个数.因为字符可以偏移k个单位,先用尺取法处理出每个位置能够取到的字符.设模式串长度为m.

令\(C(m-1+k) = \sum_{i=0}^{m-1}A_{i+k}*B(m-i-1)\).

反转模式串B, 对每个字符c,若该位上能够取到c,则多项式该位取1,否则为0,FFT求卷积.并记录[m-1,n-1]每个位置4次计算的系数\(C\)之和.

若系数之和=m,表示母串中以位置i结尾,长度为m的字串与B相匹配.

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 4e5 + 10;
const double PI = acos(-1.0);
struct Complex{
double x, y;
inline Complex operator+(const Complex b) const {
return (Complex){x +b.x,y + b.y};
}
inline Complex operator-(const Complex b) const {
return (Complex){x -b.x,y - b.y};
}
inline Complex operator*(const Complex b) const {
return (Complex){x *b.x -y * b.y,x * b.y + y * b.x};
}
} va[MAXN * 2 + MAXN / 2], vb[MAXN * 2 + MAXN / 2];
int lenth = 1, rev[MAXN * 2 + MAXN / 2];
int N, M; // f 和 g 的数量
//f g和 的系数
// 卷积结果
// 大数乘积
int f[MAXN],g[MAXN];
vector<LL> conv;
vector<LL> multi;
//f g
void init()
{
int tim = 0;
lenth = 1;
conv.clear(), multi.clear();
memset(va, 0, sizeof va);
memset(vb, 0, sizeof vb);
while (lenth <= N + M - 2)
lenth <<= 1, tim++;
for (int i = 0; i < lenth; i++)
rev[i] = (rev[i >> 1] >> 1) + ((i & 1) << (tim - 1));
}
void FFT(Complex *A, const int fla)
{
for (int i = 0; i < lenth; i++){
if (i < rev[i]){
swap(A[i], A[rev[i]]);
}
}
for (int i = 1; i < lenth; i <<= 1){
const Complex w = (Complex){cos(PI / i), fla * sin(PI / i)};
for (int j = 0; j < lenth; j += (i << 1)){
Complex K = (Complex){1, 0};
for (int k = 0; k < i; k++, K = K * w){
const Complex x = A[j + k], y = K * A[j + k + i];
A[j + k] = x + y;
A[j + k + i] = x - y;
}
}
}
}
void getConv(){ //求多项式
init();
for (int i = 0; i < N; i++)
va[i].x = f[i];
for (int i = 0; i < M; i++)
vb[i].x = g[i];
FFT(va, 1), FFT(vb, 1);
for (int i = 0; i < lenth; i++)
va[i] = va[i] * vb[i];
FFT(va, -1);
for (int i = 0; i <= N + M - 2; i++)
conv.push_back((LL)(va[i].x / lenth + 0.5));
} const int len = 2e5+10; char s1[len],s2[len];
int cnt[4];
int have[MAXN][4];
map<char,int> id;
LL ans[MAXN]; void debug(){
for(int i=0;i<4;++i){
for(int j=0;j<4;++j){
cout<<have[i][j]<<" ";
}
cout<<endl;
}
} int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int n,m,k;
id['A'] = 0, id['C'] = 1, id['G'] =2, id['T'] = 3;
scanf("%d %d %d",&n,&m,&k );
scanf("%s",s1);
scanf("%s",s2);
int L=0,R=-1;
for(int i=0;i<n;++i){
while(L<i-k) cnt[id[s1[L++]]]--; //退
while(R<n-1 && R<i+k) cnt[id[s1[++R]]]++; //增
for(int j=0;j<4;++j){
if(cnt[j]) have[i][j] = 1;
}
}
for(int k=0;k<4;++k){
N = n, M = m;
for(int i=0;i<N;++i){
if(have[i][k]) f[i] = 1;
else f[i] = 0;
}
for(int i=0;i<M;++i){
if(id[s2[m-i-1]]==k) g[i] = 1;
else g[i] = 0;
}
getConv();
int sz = conv.size();
for(int i=m-1;i<sz;++i){
ans[i]+= conv[i];
}
}
int res=0;
for(int i=m-1;i<n;++i){
if(ans[i]==m){
res++;
}
}
printf("%d\n",res);
return 0;
}

CodeForces - 528D Fuzzy Search (FFT求子串匹配)的更多相关文章

  1. Codeforces.528D.Fuzzy Search(FFT)

    题目链接 \(Descripiton\) 给出文本串S和模式串T和k,S,T为DNA序列(只含\(A,T,G,C\)).对于S中的每个位置\(i\),只要\(s[i-k]\sim s[i+k]\)中有 ...

  2. Codeforces 528D Fuzzy Search(FFT)

    题目 Source http://codeforces.com/problemset/problem/528/D Description Leonid works for a small and pr ...

  3. CodeForces 528D Fuzzy Search 多项式 FFT

    原文链接http://www.cnblogs.com/zhouzhendong/p/8782849.html 题目传送门 - CodeForces 528D 题意 给你两个串$A,B(|A|\geq| ...

  4. codeforces 528D Fuzzy Search

    链接:http://codeforces.com/problemset/problem/528/D 正解:$FFT$. 很多字符串匹配的问题都可以用$FFT$来实现. 这道题是要求在左边和右边$k$个 ...

  5. ●codeforces 528D Fuzzy Search

    题链: http://codeforces.com/problemset/problem/528/D 题解: FFT 先解释一下题意: 给出两个字符串(只含'A','T','C','G'四种字符),一 ...

  6. 2019.01.26 codeforces 528D. Fuzzy Search(fft)

    传送门 fftfftfft好题. 题意简述:给两个字符串s,ts,ts,t,问ttt在sss中出现了几次,字符串只由A,T,C,GA,T,C,GA,T,C,G构成. 两个字符匹配的定义: 当si−k, ...

  7. CF 528D. Fuzzy Search NTT

    CF 528D. Fuzzy Search NTT 题目大意 给出文本串S和模式串T和k,S,T为DNA序列(只含ATGC).对于S中的每个位置\(i\),只要中[i-k,i+k]有一个位置匹配了字符 ...

  8. [Codeforces 580D]Fizzy Search(FFT)

    [Codeforces 580D]Fizzy Search(FFT) 题面 给定母串和模式串,字符集大小为4,给定k,模式串在某个位置匹配当且仅当任意位置模式串的这个字符所对应的母串的位置的左右k个字 ...

  9. CF528D. Fuzzy Search [FFT]

    CF528D. Fuzzy Search 题意:DNA序列,在母串s中匹配模式串t,对于s中每个位置i,只要s[i-k]到s[i+k]中有c就认为匹配了c.求有多少个位置匹配了t 预处理\(f[i][ ...

随机推荐

  1. angularJs多文件上传

    <input type="file" id="file{{$index}}" class="file{{$index}}" ngf-s ...

  2. hdu 2809(状压dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2809 思路:简单的状压dp,看代码会更明白. #include<iostream> #in ...

  3. sqlserver 安全

    1.将数据库的用户名和密码加密保存,使用加密传输.2.将数据库里面的用户除了这个用户所有的用户都禁用,把该用户的密码改的很复杂,很难破解那种3.设置数据库的可连接方式(所有的方式的设置).4.删除数据 ...

  4. JSP内置对象——session

    sessionsession表示客户端与服务器的一次会话Web中的session指的是用户在浏览某个网站时,从进入网站到浏览器关闭所进过的这段时间,也就是用户浏览这个网站所花费的时间从上述定义中可以看 ...

  5. 第一次广搜!HDU1548--A Strange Lift

    一上来看见题目就用了深搜(因为只会深搜)果断内存超限(据说时间也会超限)无奈只好开始用广搜 其实广搜的思路和深搜有很多类似的地方 不过实现的过程中用到了队列 因此有点难以理解(好吧我个人认为) 这题是 ...

  6. poj 1386

    Play on Words Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 11312   Accepted: 3862 De ...

  7. 【BZOJ1441】Min 拓展裴蜀定理

    [BZOJ1441]Min Description 给出n个数(A1...An)现求一组整数序列(X1...Xn)使得S=A1*X1+...An*Xn>0,且S的值最小 Input 第一行给出数 ...

  8. LeetCode 笔记系列16.1 Minimum Window Substring [从O(N*M), O(NlogM)到O(N),人生就是一场不停的战斗]

    题目: Given a string S and a string T, find the minimum window in S which will contain all the charact ...

  9. 给vmware虚拟机设置Ip,使用xshell远程连接Centos

    参考下面两位的分享才弄好,发表之前先对原作者表示感谢! 给Centos配置网络以及使用xshell远程连接Centos http://www.cnblogs.com/fuly550871915/p/4 ...

  10. wordpress 忘记密码

    update wp_users set user_pass=md5("123456") where user_login='帐号';