【TJOI2017】DNA

题面

题解

对字符串一脸懵的我肯定只能用$FFT$这种暴力方法水过啊。。。

将后面那个字符串翻转一下,对$\text{AGCT}$分别统计,用$FFT$就可以啦

代码

#include<cstdio>
#include<cstring>
#include<cctype>
#include<cmath>
#include<algorithm>
#define RG register

const int maxn(200010);
const double pi(acos(-1));
const char DNA[] = "AGCT";
struct complex { double x, y; } A[maxn], B[maxn];
inline complex operator + (const complex &lhs, const complex &rhs)
	{ return (complex) {lhs.x + rhs.x, lhs.y + rhs.y}; }
inline complex operator - (const complex &lhs, const complex &rhs)
	{ return (complex) {lhs.x - rhs.x, lhs.y - rhs.y}; }
inline complex operator * (const complex &lhs, const complex &rhs)
{
	return (complex) {lhs.x * rhs.x - lhs.y * rhs.y,
		lhs.y * rhs.x + lhs.x * rhs.y};
}

char C[maxn], S[maxn];
int n, m, ans[maxn], N, r[maxn], P, T;
template<int opt> void FFT(complex *p)
{
	for(RG int i = 1; i < N; i++) if(i < r[i]) std::swap(p[i], p[r[i]]);
	for(RG int i = 1; i < N; i <<= 1)
	{
		complex rot = (complex) {cos(pi / i), opt * sin(pi / i)};
		for(RG int j = 0; j < N; j += i << 1)
		{
			complex w = (complex) {1, 0};
			for(RG int k = 0; k < i; ++k, w = w * rot)
			{
				complex x = p[j + k], y = w * p[i + j + k];
				p[j + k] = x + y, p[i + j + k] = x - y;
			}
		}
	}
}

int main()
{
	scanf("%d", &T);
	while(T--)
	{
		scanf("%s%s", C, S);
		n = strlen(C), m = strlen(S); std::reverse(S, S + m);
		for(N = 1, P = 0; N < n + m; N <<= 1, ++P);
		std::fill(ans, ans + n, 0);
		for(RG int i = 1; i < N; i++)
			r[i] = (r[i >> 1] >> 1) | ((i & 1) << (P - 1));
		for(RG int p = 0; p < 4; ++p)
		{
			for(RG int i = 0; i < N; i++) A[i] = B[i] = (complex) {0, 0};
			for(RG int i = 0; i < n; i++)
				A[i] = (complex) {(C[i] == DNA[p]) ? 1. : 0., 0};
			for(RG int i = 0; i < m; i++)
				B[i] = (complex) {(S[i] == DNA[p]) ? 1. : 0., 0};
			FFT<1>(A); FFT<1>(B);
			for(RG int i = 0; i < N; i++) A[i] = A[i] * B[i];
			FFT<-1>(A);
			for(RG int i = m - 1; i < n; i++) ans[i] += (int) (A[i].x / N + .5);
		}
		int cnt = 0;
		for(RG int i = m - 1; i < n; i++) if(ans[i] + 3 >= m) ++cnt;
		printf("%d\n", cnt);
	}
	return 0;
}

原文地址:https://www.cnblogs.com/cj-xxz/p/10240228.html

时间: 2024-08-01 12:32:40

【TJOI2017】DNA的相关文章

【POJ3691】 DNA repair (AC自动机+DP)

DNA repair Time Limit: 2000MS Memory Limit: 65536KB 64bit IO Format: %I64d & %I64u Description Biologists finally invent techniques of repairing DNA that contains segments causing kinds of inherited diseases. For the sake of simplicity, a DNA is repr

【POJ3691】DNA repair(AC自动机,DP)

题意: 生物课上我们学到,DNA序列中只有A, C, T和G四种片段. 经科学发现,DNA序列中,包含某些片段会产生不好的基因,如片段"ATC"是不好片段,则"AGATCC", "CATCAA", "ATCATC"都是不好的DNA序列,这些不好片段我们可以称为病毒片段. 现在已知m个病毒片段, 然后给定一个DNA串,问如果使用最少的修改(将DNA中的某个字母,变为其他字母,比如A变T,但变的字母也只能是"ACTG&q

【POJ2778】DNA Sequence(AC自动机)

题意: 生物课上我们学到,DNA序列中只有A, C, T和G四种片段. 经科学发现,DNA序列中,包含某些片段会产生不好的基因,如片段"ATC"是不好片段,则"AGATCC", "CATCAA", "ATCATC"都是不好的DNA序列,这些不好片段我们可以称为病毒片段. 现在已知m个病毒片段, 问长度为n的DNA序列,有多少种可能不包含病毒片段.答案可能很大,取模 100000. [数据规模和约定] 0<=m<=1

【POJ】2278 DNA Sequence

各种wa后,各种TLE.注意若AC非法,则ACT等一定非法.而且尽量少MOD. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 using namespace std; 6 7 #define MAXN 105 8 #define NXTN 4 9 10 char str[15]; 11 12 typedef struct Matrix {

【OpenJudge9270】【Pku2440】【递推】DNA

DNA [描述] A kind of virus has attacked the X planet, and many lives are infected. After weeks of study, The CHO (Creature Healthy Organization) of X planet finally finds out that this kind of virus has two kind of very simple DNA, and can be  represen

【bzoj4889】: [Tjoi2017]不勤劳的图书管理员 分块-BIT

[bzoj4889]: [Tjoi2017]不勤劳的图书管理员 题目大意:给定一个序列(n<=50000),每个数有一个编码ai(ai<=50000)和权值vi(vi<=100000),每次交换两个数的位置,交换m次(m<=50000) 求每次交换后的序列的杂乱度对1e9+7取模(对于每一对是逆序对的编码会产生两者权值和的杂乱度). 感觉正解是什么奇怪的树套树?蒟蒻只会分块水题.. 先用BIT求一遍初始状态的杂乱度..(不要问我为什么一开始是BIT..因为打暴力正好用到就懒得改了.

【bzoj4887】:[Tjoi2017]可乐 矩阵乘法,快速幂

[bzoj4887]:[Tjoi2017]可乐 题目大意:一张无相连通图(n<=30),从1号点开始走,每秒可以走到相邻的点也可以自爆,求第t秒(t<=1e6)后所有的方案数是多少对2017取模 恩..就是一个矩阵快速幂..矩阵就是原图的邻接矩阵..然后f[i][i]也是1.. 但是这是不会自爆的情况下的矩阵,算上自爆的话要把每次转移的结果求和..蒟蒻想了半天.. 然后发现其实只要再加一行一列,然后f[n+1][i]=1,就可以了.. 意会一下好了..矩阵什么的感觉讲不清楚啊.. 1 /* h

【bzoj4888】: [Tjoi2017]异或和 BIT-乱搞

[bzoj4888]: [Tjoi2017]异或和 题目大意:给定一个序列,求这个序列所有的连续和的异或值.(n<=1e5 ai<=1e6) 想了各种奇怪的方法就是不会做啊啊啊.. Orz 参考了一下http://www.cnblogs.com/xiejiadong/p/6815269.html才会做的.. 恩因为不超过20位..所以可以考虑枚举所有连续和在第i位1的个数 预处理完前缀和就可以O(1)求出任意一个连续和.. 当考虑到第i位的时候,把前缀和扫一遍 当扫到第x个前缀和sum[x],

【LeetCode】Repeated DNA Sequences 解题报告

[题目] All DNA is composed of a series of nucleotides abbreviated as A, C, G, and T, for example: "ACGAATTCCG". When studying DNA, it is sometimes useful to identify repeated sequences within the DNA. Write a function to find all the 10-letter-lon