后缀数组 模板 (敲定)
2016-05-11 13:57
561 查看
#include<iostream> #include<cstring> #include<cstdio> using namespace std; const int max_n=2e5+5; int n,m=300,sa[max_n],c[max_n],x[max_n],y[max_n],rank[max_n],height[max_n]; char s[max_n]; inline void build_sa(){ for (int i=0;i<m;++i) c[i]=0; for (int i=0;i<n;++i) c[x[i]=s[i]]++; for (int i=1;i<m;++i) c[i]+=c[i-1]; for (int i=n-1;i>=0;--i) sa[--c[x[i]]]=i; for (int k=1;k<=n;k<<=1){ int p=0; for (int i=n-k;i<n;++i) y[p++]=i; for (int i=0;i<n;++i) if (sa[i]>=k) y[p++]=sa[i]-k; for (int i=0;i<m;++i) c[i]=0; for (int i=0;i<n;++i) c[x[y[i]]]++; for (int i=1;i<m;++i) c[i]+=c[i-1]; for (int i=n-1;i>=0;--i) sa[--c[x[y[i]]]]=y[i]; swap(x,y); p=1; x[sa[0]]=0; for (int i=1;i<n;++i) x[sa[i]]=y[sa[i-1]]==y[sa[i]]&& ((sa[i-1]+k>=n?-1:y[sa[i-1]+k])==(sa[i]+k>=n?-1:y[sa[i]+k]))?p-1:p++; if (p>n) break; m=p; } } inline void build_lcp(){ for (int i=0;i<n;++i) rank[sa[i]]=i; height[0]=0; int k=0; for (int i=0;i<n;++i){ if (!rank[i]) continue; if (k) --k; int j=sa[rank[i]-1]; while (i+k<n&&j+k<n&&s[i+k]==s[j+k]) ++k; height[rank[i]]=k; } } int main(){ gets(s); n=strlen(s); build_sa(); build_lcp(); for (int i=0;i<n;++i) printf("%d%c",sa[i]+1," \n"[i==n-1]); for (int i=0;i<n;++i) printf("%d%c",height[i]," \n"[i==n-1]); }
相关文章推荐
- iOS-顶部提示框源码分享,在顶部弹出提示框
- 获取url文件名和扩展名及服务器路径的方法
- JS 整型,浮点型转化为字符型
- Elasticsearch之API CUED操作
- rspec中的shared_examples与shared_context有什么不同
- 用CSS下划线距离
- C# WinForm TreeListView控件用法初步
- PAT (Basic Level) Practise (中文)1039. 到底买不买(20)
- HBase -ROOT-和.META.表结构(region定位原理)
- Form authentication(表单认证)问题
- Js 冒泡事件阻止
- 非空判断注意
- Percona-tookit学习笔记(三)
- shell /bin/bash^M: bad interpreter错误解决
- btrfs文件系统管理
- Linux Pthread fork 探究
- java自动生成目录树
- java打包jdk版本问题
- MediaPlayer与SoundPool的使用场景
- mac osx 搭建8266开发环境简单记录