#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());
}

最新文章

  1. sqlserver删除所有表(表结构和数据)
  2. Java面试宝典2015版(绝对值得收藏超长版)
  3. 在OCR文字识别软件选项卡中怎么设置图像和文字
  4. C++调用GDAL库读取并输出tif文件,并计算斑块面积输出景观指数:CSD
  5. window.history
  6. Max Sub-matrix
  7. 获取datagrid中编辑列combobox的value值与text值
  8. redhat开启linux server
  9. ubuntu server 时区设置问题解决
  10. kettle闪退问题
  11. 洗礼灵魂,修炼python(84)-- 知识拾遗篇 —— 网络编程之socket
  12. C语言学习之桶排序
  13. docker 将正在运行的容器打包为镜像
  14. virtualbox 采用 NAT 还是 BRIDGE
  15. whereis+whatis+man
  16. &lt;context:component-scan&gt;子标签:&lt;context:include-filter&gt;和&lt;context:exclude-filter&gt;使用时要注意的地方
  17. Node.js读取文件内容
  18. 【linux基础】core dump debug
  19. 【LG3240】[HNOI2015]实验比较
  20. java8新增的日期时间包

热门文章

  1. PHP队列类
  2. 项目管理知识图谱OR架构图
  3. python findall函数
  4. PHP原生DOM对象操作XML的方法解答
  5. uml设计之多重性
  6. 实现手机网页调起原生微信朋友圈分享的工具nativeShare.js
  7. 操作系统之LRU算法 C语言链表实现
  8. 软件测试 → 第二章 基础-&gt; 软件缺陷与缺陷管理
  9. 2019-4-29-dotnet-core-通过-frp-发布自己的网站
  10. oralce如何修改默认的XDB监听端口