#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = ;
char s[maxn];
int sa[maxn], t[maxn], t2[maxn], c[maxn];
int n;
//构造字符串s的后缀数组, 每个字符值必须为0 ~ m-1
void build_sa(int m) {
int *x = t, *y = t2;
//基数排序
for(int i = ; i < m; i++) c[i] = ;
for(int i = ; i < n; i++) c[x[i] = s[i]]++;
for(int i = ; i < m; i++) c[i] += c[i-];
for(int i = n-; i >= ; i--) sa[--c[x[i]]] = i;
for(int k = ; k <= n; k <<= ) {
int p = ;
//直接利用sa数组排序第二关键字
for(int i = n-k; i < n; i++) y[p++] = i;
for(int i = ; i < n; i++) if(sa[i] >= k) y[p++] = sa[i] - k;
//基数排序第一关键字
for(int i = ; i < m; i++) c[i] = ;
for(int i = ; i < n; i++) c[x[y[i]]]++;
for(int i = ; i < m; i++) c[i] += c[i-];
for(int i = n-; i>= ; i--) sa[--c[x[y[i]]]] = y[i];
//根据sa和y数组计算新的x数组
swap(x, y);
p = ;
x[sa[]] = ;
for(int i = ; i < n; i++)
x[sa[i]] = (y[sa[i-]] == y[sa[i]] && y[sa[i-]+k] == y[sa[i]+k] ? p- : p++);
if(p >= n) break;
m = p;
}
} int rank_[maxn]; //rank[i]代表后缀i在sa数组中的下标
int height[maxn]; //height[i] 定义为sa[i-1] 和 sa[i] 的最长公共前缀
//后缀j和k的LCP长度等于RMQ(height, rank[j]+1, rank[k])
void get_height() {
int i, j, k = ;
for(int i = ; i < n; i++) rank_[sa[i]] = i;
for(int i = ; i < n; i++) {
if(!rank_[i]) continue;
int j = sa[rank_[i]-];
if(k) k--; while(s[i+k] == s[j+k]) k++;
height[rank_[i]] = k;
}
}
int d[maxn][];
void rmq_init() {
for(int i = ; i < n; i++) d[i][] = height[i];
for(int j = ; (<<j) <= n; j++)
for(int i = ; i + (<<j) - < n; i++)
d[i][j] = min(d[i][j-], d[i+(<<(j-))][j-]);
}
int rmq(int l, int r) {
if(l == r) return n-l;
if(rank_[l] > rank_[r]) swap(l, r);
int L = rank_[l]+;
int R = rank_[r];
int k = ;
while((<<(k+)) <= R-L+) k++;
return min(d[L][k], d[R-(<<k)+][k]);
}
//LCP加速多模式匹配
int m;
int cmp_suffix(char* P, int p, int c,int &k) {
k = ;
int i;
for(i = ; P[c+i] == s[sa[p]+c+i]; i++) {
if(P[c+i] == '\0')
return ;
k++;
}
if(P[c+i] == '\0')
return ;
return P[c+i] - s[sa[p]+c+i];
}
vector<int> A;
void b_search(char*P, int L, int R) {
int k;
if(cmp_suffix(P, L, , k) < ) return ;
if(cmp_suffix(P, R, , k) > ) return ;
int c = , rr = ;
int lst = -;
k = ;
while(R >= L) {
int M = L + (R-L)/;
if(lst != -) c = rmq(lst, sa[M]);
if(c <= k) {
int res = cmp_suffix(P, M, c, k);
rr = res;
if(!res) {
A.push_back(sa[M]);
b_search(P, L, M-);
b_search(P, M+, R);
return;
}
lst = sa[M];
if(res < ) R = M-; else L = M+;
}
else if(rr < )R = M-;
else L = M+;
}
}
void find(char* P) { //找到全部的匹配位置存入A数组中
A.clear();
m = strlen(P);
int L = , R = n-;
b_search(P, L, R);
sort(A.begin(), A.end());
}

后缀数组 + LCP加速多模式匹配算法 O(m+logn)的更多相关文章

  1. poj 2774 Long Long Message 后缀数组LCP理解

    题目链接 题意:给两个长度不超过1e5的字符串,问两个字符串的连续公共子串最大长度为多少? 思路:两个字符串连接之后直接后缀数组+LCP,在height中找出max同时满足一左一右即可: #inclu ...

  2. hdu 3518 Boring counting 后缀数组LCP

    题目链接 题意:给定长度为n(n <= 1000)的只含小写字母的字符串,问字符串子串不重叠出现最少两次的不同子串个数; input: aaaa ababcabb aaaaaa # output ...

  3. hdu 4691 最长的共同前缀 后缀数组 +lcp+rmq

    http://acm.hdu.edu.cn/showproblem.php? pid=4691 去年夏天,更多的学校的种族称号.当时,没有后缀数组 今天将是,事实上,自己的后缀阵列组合rmq或到,但是 ...

  4. 后缀数组LCP + 二分 - UVa 11107 Life Forms

    Life Forms Problem's Link Mean: 给你n个串,让你找出出现次数大于n/2的最长公共子串.如果有多个,按字典序排列输出. analyse: 经典题. 直接二分判断答案. 判 ...

  5. UVA 11107 Life Forms——(多字符串的最长公共子序列,后缀数组+LCP)

    题意: 输入n个序列,求出一个最大长度的字符串,使得它在超过一半的DNA序列中连续出现.如果有多解,按照字典序从小到大输出所有解. 分析:这道题的关键是将多个字符串连接成一个串,方法是用不同的分隔符把 ...

  6. POJ2774 Long Long Message 【后缀数组lcp】

    长长的消息 时间限制: 4000MS   内存限制: 131072K 提交总数: 32393   接受: 13079 案件时间限制: 1000MS 描述 小猫在拜特兰的首府物理专业.最近有一个不幸的消 ...

  7. 【BZOJ】1692 & 1640: [Usaco2007 Dec]队列变换(后缀数组+贪心)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1692 http://www.lydsy.com/JudgeOnline/problem.php?id ...

  8. bzoj 4278 Tasowanie 后缀数组+贪心

    题目大意 给定两个数字串A和B,通过将A和B进行二路归并得到一个新的数字串T,请找到字典序最小的T.\(len \leq 200000\) 题解 我们从归并排序的角度去想,每次把两者之一较小的取出来 ...

  9. poj 3261 后缀数组 找反复出现k次的子串(子串能够重叠)

    题目:http://poj.org/problem?id=3261 仍然是后缀数组的典型应用----后缀数组+lcp+二分 做的蛮顺的,1A 可是大部分时间是在调试代码.由于模板的全局变量用混了,而自 ...

随机推荐

  1. MySQL遇到经典例子--(遇到就写)

    1,一般的搜索只会搜索标题,也有特殊的情况,就是标题和内容一起搜索! -- 模糊搜索只是搜索标题 $sql = "select count(*) as sum from publish wh ...

  2. Hdu 4291

    题目链接 这道题, 给我的最大的知识点就是对于去模运算,一定可以找到循环节,这题只不过是嵌套了两层,可以分别找到循环节.关于这题如何找循环节的,直接暴力,网上也有很多. 找到循环节之后,另一个知识点就 ...

  3. hdu5444 乱搞 长春网赛

    可以暴力. #include<iostream> #include<cstring> #define maxn 1100 using namespace std; int a[ ...

  4. linux驱动开发满三年,回首一下基本看不到其它选择

    刚刚搞完一个处理器BSP项目,准备搞下一个自研处理器.说不上来什么喜悦,仅仅有些许茫然.没有刚毕业时对这个行业的痴迷,慢慢认同这仅仅是个谋生工具的想法. 回忆当初编写第一个驱动,就像上了战场.被长官踢 ...

  5. DirectX11 With Windows SDK--07 添加光照与常用几何模型、光栅化状态

    原文:DirectX11 With Windows SDK--07 添加光照与常用几何模型.光栅化状态 前言 对于3D游戏来说,合理的光照可以让游戏显得更加真实.接下来会介绍光照的各种分量,以及常见的 ...

  6. Oracle安装 卸载 和常见问题

    Oracle的安装   全局数据库名:orcl  口令:orcl 或者以第三方工具SQLplus为例 系统用户:sys 和 system  练习账户:scott (密码:tiger) 登录账户为:sy ...

  7. [Linux]jenkins的安装 标签: linux服务器 2016-08-21 20:47 1060人阅读 评论(23)

    现阶段遇到一个问题,因为某台服务器需要腾出来,所以需要将这台服务器上jenkins的主节点重新安装到另外一台服务器上.,下面就介绍一下centos7上面jenkins的安装. 一,步骤 注意:新安装的 ...

  8. Java面向对象----继承概念,super关键字

    继承概念: 继承需要符合的关系  is-a  , 父类通用更抽象,子类更特殊更具体 类之间的关系 继承体现 组合体现 实现接口体现 继承的意义 代码重用 体现不同抽象层次 extends关键字 Sup ...

  9. 阿里开源!轻量级深度学习端侧推理引擎 MNN

    阿里妹导读:近日,阿里正式开源轻量级深度学习端侧推理引擎“MNN”. AI科学家贾扬清如此评价道:“与 Tensorflow.Caffe2 等同时覆盖训练和推理的通用框架相比,MNN 更注重在推理时的 ...

  10. redhat6.5安装oracle11_2R

    参照前人一步一步操作: http://leihenzhimu.blog.51cto.com/3217508/1685164 遇到如下错误: This is a prerequisite conditi ...