[CF528D]Fuzzy Search

luogu

sol

这种字符串匹配的问题显然可以把一个串\(reverse\)过来然后用\(FFT\)做吧。
对每种字母分开考虑,设两个多项式\(A(x),B(x)\),其中
\[A(x)=\sum_{i=0}^{n-1}[区间[i-k,i+k]内存在该种字符]x^i\]
\[B(x)=\sum_{i=0}^{n-1}[t[i]为该种字符]x^i\]
然后两个多项式卷一下就是这种字符在第\(i\)个位置上的匹配吧。
最后对每次的系数求和,若恰好等于\(|T|\)则说明匹配成功。
复杂度\(O(4n\log n)\)

code

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
const int _ = 8e5+5;
const double Pi = acos(-1);
struct Complex{
    double rl,im;
    Complex(){rl=im=0;}
    Complex(double a,double b){rl=a,im=b;}
    Complex operator + (Complex b)
        {return Complex(rl+b.rl,im+b.im);}
    Complex operator - (Complex b)
        {return Complex(rl-b.rl,im-b.im);}
    Complex operator * (Complex b)
        {return Complex(rl*b.rl-im*b.im,rl*b.im+im*b.rl);}
}w[_],a[_],b[_];
int N,n,m,k,rev[_],l,tmp[_],ans[_],Ans;
char s[_],t[_],fg[4]={'A','G','C','T'};
void FFT(Complex *P,int opt)
{
    for (int i=0;i<N;++i) if (i<rev[i]) swap(P[i],P[rev[i]]);
    for (int i=1;i<N;i<<=1)
        for (int p=i<<1,j=0;j<N;j+=p)
            for (int k=0;k<i;++k)
            {
                Complex W=w[N/i*k];W.im*=opt;
                Complex X=P[j+k],Y=W*P[j+k+i];
                P[j+k]=X+Y;P[j+k+i]=X-Y;
            }
    if (opt==-1) for (int i=0;i<N;++i) P[i].rl/=N;
}
int main()
{
    scanf("%d%d%d",&n,&m,&k);scanf("%s%s",s,t);reverse(t,t+m);
    for (N=1;N<n+m;N<<=1) ++l;--l;
    for (int i=0;i<N;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<l);
    for (int i=0;i<N;++i) w[i]=Complex(cos(Pi*i/N),sin(Pi*i/N));
    for (int zsy=0;zsy<4;++zsy)
    {
        for (int i=0;i<N;++i) a[i].rl=a[i].im=b[i].rl=b[i].im=0;
        for (int i=0,pos=-1e9;i<n;++i)
        {
            if (s[i]==fg[zsy]) pos=i;
            if (pos>=i-k) a[i].rl=1;
        }
        for (int i=n-1,pos=1e9;~i;--i)
        {
            if (s[i]==fg[zsy]) pos=i;
            if (pos<=i+k) a[i].rl=1;
        }
        for (int i=0;i<m;++i) if (t[i]==fg[zsy]) b[i].rl=1;
        FFT(a,1);FFT(b,1);
        for (int i=0;i<N;++i) a[i]=a[i]*b[i];
        FFT(a,-1);
        for (int i=0;i<n;++i) ans[i]+=(int)(a[i].rl+0.5);
    }
    for (int i=0;i<n;++i) if (ans[i]==m) ++Ans;
    printf("%d\n",Ans);return 0;
}

原文地址:https://www.cnblogs.com/zhoushuyu/p/8728888.html

时间: 2024-10-05 05:04:52

[CF528D]Fuzzy Search的相关文章

CF528D Fuzzy Search (生成函数+FFT)

题目传送门 题目大意:给你两个只包含A,G,C,T的字符串$S$,$T$,$S$长$T$短,按照如下图方式匹配 解释不明白直接上图 能容错的距离不超过$K$,求能$T$被匹配上的次数 $S$串同一个位置可以被$T$的不同位置匹配多次 对4种字符分别处理,假设我们现在只讨论字符A 对于字符串AGCAATTCAT,字符A的生成函数就是1001100010 题目要求距离不超过K就能匹配,把周围距离不超过$K$的位置都变成1,形成一个新串$S'$ $S$  1001100010 $S'$ 1111110

Fuzzy Search

题意: 考虑模板串B和给定串A,给定K,对于模板串上给定位置j的字符,如果能在给定串上i左右K个字符内找到相同字符,则说可以匹配. 问有多少匹配. 解法: 考虑对于每一种字符分开求. 对于当前字符ch,将B串中为此字符的位置标为1其他位置为0,将A串中所有可以匹配ch的位置标为1,其他为0,这样 记$c_i$表示以 i 为起点字符ch可以匹配到几个. $$c_i = \sum_{ 0 \leq j<m} { b_j a_{i+j} }$$ $$c_i = \sum_{0 \leq k \leq

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

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>

FFT的应用

FFT的应用 概述 FFT的模板很简单,大家都会背,于是出题的空间就在于建模了.FFT的题目难在建模,往往需要将问题抽象出来,经过一系列转化后得到乘积式的和,再赋予式子各个项的系数一定的意义即可. 基本形式 对于类似\(\sum_{i+j=N+k}a_ib_j\)的式子,可以直接通过FFT计算. 其中N是定值,表示元素个数:k是变量,是题目中的系数,a和b是间接已知数组,当a与b的系数和为定值时,可将一个翻转,否则直接计算. 例题:P3723?[AH2017/HNOI2017]礼物 直接计算卷积

Postgres full-text search is Good Enough!

When you have to build a web application, you are often asked to add search. The magnifying glass is something that we now add to wireframes without even knowing what we are going to search. Search has became an important feature and we've seen a big

FULL TEXT SEARCH

1. During data access through Information Access Service, Fuzzy Search queries are routed to the search engine, while linguistic processing is handled by the text proccessor. 2. For data type TEXT and SHORTTEXT,  the index creation is done during tab

Lucene 基础理论

1. 全文检索系统与Lucene简介 1.1 什么是全文检索与全文检索系统 全文检索是指计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式.这个过程类似于通过字典中的检索字表查字的过程. 全文检索的方法主要分为按字检索和按词检索两种.按字检索是指对于文章中的每一个字都建立索引,检索时将词分解为字的组合.对于各种不同的语言而言,字有不同的含义,比如英文中字与词实际上

Elasticsearch 常用基本查询

安装启动很简单,参考官网步骤:https://www.elastic.co/downloads/elasticsearch 为了介绍Elasticsearch中的不同查询类型,我们将对带有下列字段的文档进行搜索:title(标题),authors(作者),summary(摘要),release date(发布时间)以及number of reviews(评论数量),首先,让我们创建一个新的索引,并通过bulk API查询文档: 为了展示Elasticsearch中不同查询的用法,首先在Elast