Sa求法
2016-04-27 16:37
351 查看
#include <iostream> #include <cstdio> #include <math.h> #include <algorithm> #include <string.h> using namespace std; const int MAXN=20010; int t1[MAXN],t2[MAXN],c[MAXN]; bool cmp(int *r,int a,int b,int l) { return r[a]==r[b] && r[a+l]== r[b+l]; } void da(int str[],int sa[],int Rank[],int height[],int n,int m) { n++; int i,j,p,*x =t1,*y=t2; for (int i=0;i<m;i++) c[i]=0; for (int i=0;i<n;i++) c[x[i]=str[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 j=1;j<=n;j <<=1) { p=0; for (int i=n-j; i<n ; i++) y[p++] =i; for (int i=0; i<n; i++) if (sa[i]>=j) y[p++]=sa[i]-j; 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]] = cmp(y,sa[i-1],sa[i],j)?p-1:p++; if (p>=n) break; m=p; } int k=0; n--; for (int i=0;i<=n;i++) Rank[sa[i]]=i; for (int i=0;i<n;i++) { if (k) k--; j=sa[Rank[i]-1]; while (str[i+k]==str[j+k]) k++; height [Rank[i]] =k; } } int Rank[MAXN],height[MAXN]; int RMQ[MAXN]; int mm[MAXN]; int best[20][MAXN]; void initRMQ(int n) { mm[0]=-1; for (int i=1;i<=n;i++) mm[i] = ((i&(i-1)) == 0) ? mm[i-1]+1:mm[i-1]; for (int i=1;i<=n;i++) best[0][i]=i; for (int i=1;i<=mm ;i++) for (int j=1;j+(1<<i)-1<=n;j++) { int a=best[i-1][j]; int b=best[i-1][j+(1<<(i-1))]; if (RMQ[a]<RMQ[b]) best[i][j]=a; else best[i][j]=b; } } int askRMQ(int a,int b) { int t; t=mm[b-a+1]; b-=(1<<t)-1; a=best[t][a]; b=best[t][b]; return RMQ[a]<RMQ[b]?a:b; } int lcp(int a,int b) { a=Rank[a]; b=Rank[b]; if (a>b) swap(a,b); return height[askRMQ(a+1,b)]; } char str[MAXN]; int r[MAXN]; int sa[MAXN]; int main() { while (scanf("%s",str) ==1 ) { int len=strlen(str); int n=2*len+1; for (int i=0;i<len;i++) r[i]=str[i]; for (int i=0;i<len;i++) r[len+1+i] = str[len-1-i]; r[len] = 1; r = 0; da(r,sa,Rank,height,n,250); for (int i=1;i<=n;i++) RMQ[i]=height[i]; initRMQ(n); int ans=0,st; int tmp; for (int i=0;i<len;i++) { tmp=lcp(i,n-i); if (2*tmp>ans) { ans=2*tmp; st=i-tmp; } tmp=lcp(i,n-i-1); if (2*tmp-1>ans) { ans=2*tmp-1; st=i-tmp+1; } } str[st+ans]=0; printf("%d\n",ans); } return 0; }
相关文章推荐
- 如何组织构建多文件 C 语言程序(二)
- 如何写好 C main 函数
- Lua和C语言的交互详解
- 关于C语言中参数的传值问题
- 简要对比C语言中三个用于退出进程的函数
- 深入C++中API的问题详解
- 基于C语言string函数的详解
- C语言中fchdir()函数和rewinddir()函数的使用详解
- C语言内存对齐实例详解
- C语言编程中统计输入的行数以及单词个数的方法
- C语言自动生成enum值和名字映射代码
- 使用C语言判断英文字符大小写的方法
- c语言实现的带通配符匹配算法
- C语言实现顺序表基本操作汇总
- C语言中计算正弦的相关函数总结
- 使用C语言详解霍夫曼树数据结构
- C语言实现选择排序、冒泡排序和快速排序的代码示例
- 探讨C语言的那些小秘密之断言
- C语言实现BMP转换JPG的方法
- 深入探讨C语言中局部变量与全局变量在内存中的存放位置