Fuzzy Search

题意:

给定一个模式串和目标串按下图方式匹配,错开位置不多于k

解题思路:

总共只有\(A C G T\)四个字符,那么我们可以按照各个字符进行匹配,比如按照\(A\)进行匹配时,当\(k=1\)时,我们将目标串

\(ACAT\)化作

\(1~0~1~0\)

模式串

\(AGCAATTCAT\)化作

\(1~1~1~1~1~1~0~1~1~1\)

同样是反置目标串

可以得到以x为匹配终点的位置的匹配函数\(p(X)=\sum_{i+j=x}A(i)B(j)\)

如此进行4次FFT,最后如果目标位置贡献等于目标串长度,则说明匹配成功

#include <bits/stdc++.h>
using namespace std;
/* freopen("k.in", "r", stdin);
freopen("k.out", "w", stdout); */
//clock_t c1 = clock();
//std::cerr << "Time:" << clock() - c1 <<"ms" << std::endl;
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#define de(a) cout << #a << " = " << a << endl
#define rep(i, a, n) for (int i = a; i <= n; i++)
#define per(i, a, n) for (int i = n; i >= a; i--)
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef vector<int, int> VII;
#define inf 0x3f3f3f3f
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll MAXN = 1e6 + 7;
const ll MAXM = 1e6 + 7;
const ll MOD = 998244353;
const double eps = 1e-6;
const double pi = acos(-1.0);
template <class T>
inline void in(T &x)
{
static char ch;
static bool neg;
for (ch = neg = 0; ch < '0' || '9' < ch; neg |= ch == '-', ch = getchar())
;
for (x = 0; '0' <= ch && ch <= '9'; (x *= 10) += ch - '0', ch = getchar())
;
x = neg ? -x : x;
} struct Complex
{
double x, y;
Complex(double xx = 0, double yy = 0) { x = xx, y = yy; }
} a[MAXN], b[MAXN], c[MAXN], ans[MAXN];
Complex operator+(Complex a, Complex b) { return Complex(a.x + b.x, a.y + b.y); }
Complex operator-(Complex a, Complex b) { return Complex(a.x - b.x, a.y - b.y); }
Complex operator*(Complex a, Complex b) { return Complex(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x); } //不懂的看复数的运算那部分
int N, M;
int l, r[MAXN];
int limit = 1;
void FFT(Complex *A, int type)
{
for (int i = 0; i < limit; i++)
if (i < r[i])
swap(A[i], A[r[i]]); //求出要迭代的序列
for (int mid = 1; mid < limit; mid <<= 1)
{ //待合并区间的长度的一半
Complex Wn(cos(pi / mid), type * sin(pi / mid)); //单位根
for (int R = mid << 1, j = 0; j < limit; j += R)
{ //R是区间的长度,j表示前已经到哪个位置了
Complex w(1, 0); //幂
for (int k = 0; k < mid; k++, w = w * Wn)
{ //枚举左半部分
Complex x = A[j + k], y = w * A[j + mid + k]; //蝴蝶效应
A[j + k] = x + y;
A[j + mid + k] = x - y;
}
}
}
/*if (type == -1)
for (int i = 0; i < limit; ++i)
a[i].x /= limit;//我们推过的公式里面有一个1/n这一项*/
}
char s[MAXN], t[MAXN];
void init(int N, int M)
{
while (limit <= N + M)
limit <<= 1, l++;
for (int i = 0; i < limit; i++)
r[i] = (r[i >> 1] >> 1) | ((i & 1) << (l - 1));
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
}
int change(char str)
{
if (str == 'A')
return 1;
else if (str == 'T')
return 2;
else if (str == 'G')
return 3;
else
return 4;
}
int pre[MAXN], cnt;
int main()
{
int n, m, k;
scanf("%d%d%d %s %s", &n, &m, &k, s, t);
reverse(t, t + m);
init(n, m);
for (int ca = 1; ca <= 4; ca++)
{
cnt = -1;
memset(pre, 0, sizeof(pre));
memset(a, 0, sizeof(a));
memset(b, 0, sizeof(b));
for (int i = 0; i < n; i++)
{
if (change(s[i]) == ca)
pre[++cnt] = i;
a[i].x = change(s[i]) == ca ? 1 : 0, a[i].y = 0;
}
for (int i = 0; i < m; i++)
b[i].x = change(t[i]) == ca ? 1 : 0, b[i].y = 0;
int now = -1;
for (int i = 0; i <= cnt; i++)
{
int L = max(pre[i] - k, 0);
int R = min(pre[i] + k, n - 1);
if (now > R)
continue;
now = max(L, now);
for (; now <= R; now++)
a[now].x = 1;
now--;
}
FFT(a, 1);
FFT(b, 1);
for (int i = 0; i < limit; i++)
a[i] = b[i] * a[i];
FFT(a, -1);
for (int i = 0; i < limit; i++)
c[i] = c[i] + a[i];
}
int ans = 0;
for (int i = m - 1; i < limit; i++)
if (int(c[i].x / limit + 0.5) == m)
ans++;
printf("%d\n", ans);
return 0;
}

CF-528D Fuzzy Search(FFT字符串匹配)的更多相关文章

  1. CF 528D. Fuzzy Search NTT

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

  2. 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]\)中有 ...

  3. CodeForces - 528D Fuzzy Search (FFT求子串匹配)

    题意:求母串中可以匹配模式串的子串的个数,但是每一位i的字符可以左右偏移k个位置. 分析:类似于 UVALive -4671. 用FFT求出每个字符成功匹配的个数.因为字符可以偏移k个单位,先用尺取法 ...

  4. 2018 ACM-ICPC 中国大学生程序设计竞赛线上赛 H题 Rock Paper Scissors Lizard Spock.(FFT字符串匹配)

    2018 ACM-ICPC 中国大学生程序设计竞赛线上赛:https://www.jisuanke.com/contest/1227 题目链接:https://nanti.jisuanke.com/t ...

  5. P4173 残缺的字符串(FFT字符串匹配)

    P4173 残缺的字符串(FFT字符串匹配) P4173 解题思路: 经典套路将模式串翻转,将*设为0,设以目标串的x位置匹配结束的匹配函数为\(P(x)=\sum^{m-1}_{i=0}[A(m-1 ...

  6. codeforces 528D Fuzzy Search

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

  7. CF528D. Fuzzy Search [FFT]

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

  8. 【Codeforces528D】Fuzzy Search FFT

    D. Fuzzy Search time limit per test:3 seconds memory limit per test:256 megabytes input:standard inp ...

  9. BZOJ4259: 残缺的字符串(FFT 字符串匹配)

    题意 题目链接 Sol 知道FFT能做字符串匹配的话这就是个裸题了吧.. 考虑把B翻转过来,如果\(\sum_{k = 0}^M (B_{i - k} - A_k)^2 * B_{i-k}*A_k = ...

随机推荐

  1. 【温故知新】Java web 开发(三)Form表单与上传下载文件

    简介:在一和二的基础之上,这次来记录下如何在页面提交表单数据,以及文件的上传和下载整个流程,请求也不仅限于GET了,也有POST了. 1. 为了方便,在 webapp 下直接新建一个 index.ht ...

  2. Tangram: Optimized Coarse-Grained Dataflow for Scalable NN Accelerators 阅读笔记

    目录 Tangram: Optimized Coarse-Grained Dataflow for Scalable NN Accelerators 1.Abstract 2.Introduction ...

  3. 【题解】歌唱王国(概率生成函数+KMP)+伦讲的求方差

    [题解]歌唱王国(概率生成函数+KMP)+伦讲的求方差 生成函数的本质是什么呀!为什么和It-st一样神 设\(f_i\)表示填了\(i\)个时候停下来的概率,\(g_i\)是填了\(i\)个的时候不 ...

  4. 洛谷P1002 过河卒 题解 动态规划

    题目链接:https://www.luogu.com.cn/problem/P1002 题目大意 棋盘上\(A\)点有一个过河卒,需要走到目标\(B\)点.卒行走的规则:可以向下.或者向右.同时在棋盘 ...

  5. Snipaste - 可以提高你工作效率的截图软件

    使用Snipaste提高您的工作效率 Snipaste是一个简单但功能强大的剪切工具,还允许您将屏幕截图固定在屏幕上.下载并启动应用程序,按F1开始剪切,然后按F3将其粘贴为浮动窗口.而已! 您还可以 ...

  6. POJ 2456 Aggressive cows (二分)

    题目传送门 POJ 2456 Description Farmer John has built a new long barn, with N (2 <= N <= 100,000) s ...

  7. 【Java基础总结】网络编程

    网络编程 InetAddress tcp udp

  8. 【转】ArcGIS Server 10.1 动态图层

    ArcGISServer将GIS资源以服务的方式发布,能够让更多的人在Web上浏览.使用.不过,诸如气象.环保等方面的信息是实时变化的,按照之前常规的方法,我们先要将最新获得的信息组织成地图文档后再对 ...

  9. TensorFlow——tensorflow编程基础

    0.tensorflow中的模型运行基础 tensorflow的运行机制属于定义和运行相分离,在操作层面可以抽象成两种:模型构建和模型运行. 在模型构建中的常见概念: 张量(tensor):数据,即某 ...

  10. Java 成员变量与局部变量

    成员变量与局部变量的区别 什么是局部变量.什么是成员变量: 局部变量:在方法内部的变量 形参:在方法签名中定义的变量. 方法局部变量:在方法内部定义的变量. 代码块局部变量:在代码块内定义的变量. 成 ...