[ACM模板]SuffixArray后缀数组
来源:互联网 发布:snmp 网络拓扑 编辑:程序博客网 时间:2024/06/03 13:44
#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>using namespace std;class SUFFIXARRAY {#define SLEN 201000 /* 直接用函数.solve(char s[],int charSetSize=128),s[]下标从0开始。 charSetSize:表示0<=s[0]..s[n-1]<charSetSize。0为字符串结束符,尽量别用。这个开大开小基本不影响速度。 */ /* sa[],rank[],height[i]下标为1..n (1)sa[i] : 排序后的后缀中,第i个在原串中的下标 (2)rank[i] : 原串第i个后缀,在排序后的后缀中下标,有sa[rank[i]]=i,rank[sa[i]]=i (3)height[i] : 排序后的后缀中,第i个后缀和第i-1个后缀的LCP(最长公共前缀)。有height[i]=getlcp(sa[i-1],sa[i]) (4)getlcp(i,j): 原串中,第i个后缀和第j个后缀的LCP。 */private: int s[SLEN]; int t[SLEN], t2[SLEN], c[SLEN]; int n; // 字符个数,即strlen(s) static int lg[SLEN];//lg[i]=log2(i);下取整 int f[SLEN][25]; void clear(); // m为最大字符值加1。调用之前需设置好s和n void build_sa(int m); void build_height(); void initlcp();public: SUFFIXARRAY(); int sa[SLEN]; int rank[SLEN]; int height[SLEN]; void solve(char *a,int charSetSize); int getlcp(int l,int r);//后缀 l,和后缀r的lcp};int SUFFIXARRAY::lg[SLEN];SUFFIXARRAY::SUFFIXARRAY(){ memset(lg,0,sizeof(lg)); for (int i=2;i<=n;i<<=1)lg[i]=1; for (int i=1;i<=n;i++)lg[i]+=lg[i-1];}void SUFFIXARRAY::build_height() { int i, j, k = 0; for(i = 0; i < n; i++) rank[sa[i]] = i; for(i = 0; i < n; i++) { if(k) k--; int j = sa[rank[i]-1]; while(s[i+k] == s[j+k]) k++; height[rank[i]] = k; } }void SUFFIXARRAY::initlcp(){ memset(f,0,sizeof(f)); for (int i=1;i<=n;i++)f[i][0]=height[i]; int m=lg[n]; for (int j=1;j<=m;j++) for (int i=1;i<=n;i++){ if ((i-1+(1<<j))>n)break; f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]); } }int SUFFIXARRAY::getlcp(int l,int r){//后缀 l,和后缀r的lcp if (l==r)return n-l+1; l=rank[l],r=rank[r]; if (l>r)swap(l,r);l++; int tot=lg[r-l+1]; return min(f[l][tot],f[r-(1<<(tot))+1][tot]); }void SUFFIXARRAY::build_sa(int m){ int i, *x = t, *y = t2; for(i = 0; i < m; i++) c[i] = 0; for(i = 0; i < n; i++) c[x[i] = s[i]]++; for(i = 1; i < m; i++) c[i] += c[i-1]; for(i = n-1; i >= 0; i--) sa[--c[x[i]]] = i; for(int k = 1; k <= n; k <<= 1) { int p = 0; for(i = n-k; i < n; i++) y[p++] = i; for(i = 0; i < n; i++) if(sa[i] >= k) y[p++] = sa[i]-k; for(i = 0; i < m; i++) c[i] = 0; for(i = 0; i < n; i++) c[x[y[i]]]++; for(i = 0; i < m; i++) c[i] += c[i-1]; for(i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i]; swap(x, y); p = 1; x[sa[0]] = 0; for(i = 1; i < n; i++) x[sa[i]] = y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+k]==y[sa[i]+k] ? p-1 : p++; if(p >= n) break; m = p; } }void SUFFIXARRAY::clear() { n = 0; memset(sa, 0, sizeof(sa));}void SUFFIXARRAY::solve(char *a,int charSetSize=300){ n=strlen(a)+1; for (int i=0;i<n;i++)s[i]=a[i]; s[n]=0; build_sa(charSetSize+1); build_height(); n--; for (int i=1;i<=n;i++)sa[i]++; for (int i=n;i>=1;i--)rank[i]=rank[i-1]; initlcp(); }SUFFIXARRAY sa;char s[SLEN]="abcdefghij";//s下标从0开始 ,rank[1]表示s[0]开始的后缀int i,j,k,m,n;int main(){scanf("%s",s);int m=strlen(s);s[m]=27;scanf("%s",s+m+1);n=strlen(s);sa.solve(s);int ans=0;for (i=2;i<=n;i++)if ((sa.sa[i-1]<=m&&sa.sa[i]>m)||(sa.sa[i-1]>m&&sa.sa[i]<=m))ans=max(sa.height[i],ans);cout<<ans<<endl;return 0;}main函数中实现的是:读取两个串,计算最长公共子串。
阅读全文
0 0
- [ACM模板]SuffixArray后缀数组
- 后缀数组(SuffixArray) 学习笔记
- ACM常用模板——数据结构——后缀数组
- 邝斌的ACM模板(后缀数组)
- 【后缀数组】后缀数组模板
- SuffixArray
- 后缀数组【模板】
- 【后缀数组模板】
- 后缀数组模板
- 后缀数组模板
- 【模板】后缀数组
- 后缀数组模板
- 后缀数组模板
- 后缀数组模板
- 【省选】【后缀数组】模板
- 后缀数组 模板
- 后缀数组 模板
- 后缀数组模板
- python 生成openssl rsa 私钥
- mysql source 命令导入大的sql文件的方法
- denied starting an intent without a user gesture
- Java数据结构与算法之数据结构-逻辑结构-集合(六)------集合之ArrayList和LinkedList对比
- 深入理解WEB请求过程
- [ACM模板]SuffixArray后缀数组
- APP的CPU,内存,耗电,流量测试工具
- mysql 权限用户创建
- IDCC 2017第十二届中国IDC产业年度大典即将于12月在京举办1
- 字号、pt、px、em换算对照表
- RxBus 简单使用学习
- Android 集成环信EaseUI
- android 透明式状态栏 或者 沉浸式状态栏
- APP的安全测试点