后缀数组

先开始nc了,觉得自动机做法是指数级的,就写了个后缀数组

具体方法是暴力,枚举起点,然后用lcp向后暴力匹配,如果失配就减少一次,我们一共有3次机会,这样每次匹配复杂度是O(1)的,所以总复杂度是O(nlogn+n),然后t掉了,交了发别人代码,bzoj怎么那么慢,洛谷跑的飞快。调了很长时间发现sa板子写错了,明明是粘过来的。。。

后缀自动机就是在自动机上匹配,如果不匹配可以随便走,每次匹配完统计就行了

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + ;
int n, m, k, len, pos, ans;
char s[N], t[N];
int p[N], a[N], b[N], rank[N], lcp[N], sa[N], mn[N][], mp[], Log[N], tmp[N];
void radix(int *s, int *a, int *b, int n, int m)
{
int count[N]; memset(count, , sizeof(count));
for(int i = ; i <= n; ++i) ++count[s[a[i]]];
for(int i = ; i <= m; ++i) count[i] += count[i - ];
for(int i = n; i; --i) b[count[s[a[i]]]--] = a[i];
}
void Sa(int *s, int n)
{
for(int i = ; i <= n; ++i) rank[i] = i;
radix(s, rank, sa, n, );
rank[sa[]] = ;
for(int i = ; i <= n; ++i) rank[sa[i]] = rank[sa[i - ]] + (s[sa[i]] != s[sa[i - ]]);
for(int k = ; k <= n; k <<= )
{
for(int i = ; i <= n; ++i)
{
a[i] = rank[i];
b[i] = i + k <= n ? rank[i + k] : ;
sa[i] = i;
}
radix(b, sa, rank, n, n);
radix(a, rank, sa, n, n);
rank[sa[]] = ;
for(int i = ; i <= n; ++i) rank[sa[i]] = rank[sa[i - ]] + (a[sa[i]] != a[sa[i - ]] || b[sa[i]] != b[sa[i - ]]);
}
}
void Lcp(int *s, int n)
{
int h = ;
for(int i = ; i <= n; ++i) rank[sa[i]] = i;
for(int i = ; i <= n; ++i)
{
int j = sa[rank[i] - ];
if(rank[i] <= ) continue;
if(h > ) --h;
for(; i + h <= n && j + h <= n; ++h) if(s[i + h] != s[j + h]) break;
mn[rank[i] - ][] = h;
}
for(int j = ; j <= ; ++j)
for(int i = ; i + ( << j) - <= n; ++i)
mn[i][j] = min(mn[i][j - ], mn[i + ( << (j - ))][j - ]);
}
int query(int l, int r)
{
l = rank[l];
r = rank[r];
if(l > r) swap(l, r);
--r;
int x = Log[r - l + ];
return min(mn[l][x], mn[r - ( << x) + ][x]);
}
int main()
{
int T;
scanf("%d", &T);
mp['A'] = ;
mp['G'] = ;
mp['C'] = ;
mp['T'] = ;
for(int i = ; i < N; ++i) Log[i] = Log[i >> ] + ;
while(T--)
{
ans = ;
scanf("%s%s", s + , t + );
len = ;
n = strlen(s + );
m = strlen(t + );
for(int i = ; i <= n; ++i) p[++len] = mp[s[i]];
p[++len] = ;
pos = len + ;
for(int i = ; i <= m; ++i) p[++len] = mp[t[i]];
Sa(p, len);
Lcp(p, len);
for(int i = ; i <= n - m + ; ++i)
{
int tmp = m, cnt = , p1 = i, p2 = pos;
while(tmp > )
{
int x = query(p1, p2);
tmp -= x;
p1 += x;
p2 += x;
if(tmp <= ) break;
while(cnt >= && p[p1] != p[p2] && p1 <= n && p2 <= len)
{
++p1;
++p2;
--tmp;
--cnt;
}
if(cnt < || p2 > len || p1 > n) break;
}
if(cnt >= && tmp <= ) ++ans;
}
printf("%d\n", ans);
}
return ;
}

bzoj4892的更多相关文章

  1. bzoj4892 [TJOI2017]DNA

    bzoj4892 [TJOI2017]DNA 给定一个匹配串和一个模式串,求模式串有多少个连续子串能够修改不超过 \(3\) 个字符变成匹配串 \(len\leq10^5\) hash 枚举子串左端点 ...

  2. BZOJ4892 Tjoi2017dna(后缀数组)

    对每个子串暴力匹配至失配三次即可.可以用SA查lcp.然而在bzoj上被卡常了.当然也可以二分+哈希或者SAM甚至FFT. #include<iostream> #include<c ...

  3. 【BZOJ4892】DNA(后缀数组)

    [BZOJ4892]DNA(后缀数组) 题面 BZOJ 洛谷 题解 看到这道题目,我第一反应是\(FFT\)??? 然后大力码出了一个\(FFT\) 就像这样 #include<iostream ...

  4. BZOJ4892:[TJOI2017]dna(hash)

    Description 加里敦大学的生物研究所,发现了决定人喜不喜欢吃藕的基因序列S,有这个序列的碱基序列就会表现出喜欢吃藕的性状,但是研究人员发现对碱基序列S,任意修改其中不超过3个碱基,依然能够表 ...

  5. [BZOJ4892][TJOI2017]DNA(后缀数组)

    题目描述 加里敦大学的生物研究所,发现了决定人喜不喜欢吃藕的基因序列S,有这个序列的碱基序列就会表现出喜欢吃藕的性状,但是研究人员发现对碱基序列S,任意修改其中不超过3个碱基,依然能够表现出吃藕的性状 ...

  6. 字符串Hash/树Hash学习笔记

    哈希 Tags:字符串 作业部落 评论地址 一.概述 百度百科: 散列表(Hash table/哈希表),是根据关键码值(Key value)而直接进行访问的数据结构. 哈希表常用于比较两个字符串是否 ...

  7. FFT_应用和例题

    卷积 现有两个定义在 N 上的函数 \(f(n),g(n)\),定义 \(f\) 和 \(g\) 的卷积(convolution)为 \(f \otimes g\) \[ (f \otimes g)( ...

随机推荐

  1. FFmpeg for ios架构:中级

    FFmpeg这部分想了非常久,也没找到比較好的解说方式.本来想像其他博客一样.对着代码一行行的分析.但后来感觉不太现实,FFmpeg应用在IOS上怎么说代码最少也有个5.6k行(包含音视频.业务逻辑) ...

  2. 【Unity3D自学记录】Unity3D之自制小钟表

    今天来写一个小钟表,事实上非常easy,就运用到了欧拉角. 首先创建时钟.分钟.秒钟以及4个点(12点.3点.6点.9点)偷懒了~~没弄那么多点. 时钟.分钟.秒钟这三个父级的中心一定要注意,我们旋转 ...

  3. weblogic中部署项目报错org.hibernate.QueryException: ClassNotFoundException: org.hibernate.hql.ast.HqlToken .

    原因: 原因是weblogic要查找自己的antlr,和lib下面的antlr包冲突.... 解决方法: 在weblogic.xml添加 <container-descriptor>    ...

  4. 修改 本地 IP 及 正则表达式 test exec match 的区别

    修改 IP 1.打开 "打开网络和共享中心" 2.打开 "更改适配器设置" 3.打开 "本地连接" 属性 4.修改 "协议版本 4 ...

  5. C++继承:公有,私有,保护(转)

    公有继承(public).私有继承(private).保护继承(protected)是常用的三种继承方式. 1. 公有继承(public) 公有继承的特点是基类的公有成员和保护成员作为派生类的成员时, ...

  6. C语言-回溯例2

    组合问题 组合:从n个不同元素中取r个不重复的元素组成一个子集,而不考虑其元素的顺序,称为从n个中取r个的无重组合,例如OR = {1,2,3,4}, n = 4, r = 3则无重组合为: {1,2 ...

  7. 《Python核心编程》数字类型

    1.数字类型简单介绍 Python中数字类型包含:整型.长整型.布尔型.双精度浮点型.十进制浮点型.复数.这些数字类型都是不可变类型.也就是说,改变了数字的值会生成新的对象. 在Python中删除数字 ...

  8. 【ZZ】Visual C++ 6.0 精简安装版(支持VA、ICC 等等安装)

    (2012-04-22 08:10:10) 标签: it 分类: 软件_Software Visual C++ 6.0 精简安装版(支持VA.ICC 等等安装) 2012-04-16 21:07 想找 ...

  9. 李洪强iOS开发之带placeHolder的Textview

    李洪强iOS开发之带placeHolder的Textview  01 - 创建工过程,定义全局属性,遵守textview的代理协议  02 - 添加一个textview和一个label 03 - 实现 ...

  10. bitmap进行个数统计

    昨天看了编程珠玑第一章的内容, 发现bitmap对于统计某一个范围内的整数个数效率很高, 就自己实现了一下: 这是原始的bitmap, 用于统计0~maxSize是否出现, 也可以用于排序 publi ...