poj 2774 后缀数组(模板题)
来源:互联网 发布:打开db数据库 编辑:程序博客网 时间:2024/06/14 16:48
点击打开链接
模板
#include <iostream>#include <cstring>#include <algorithm>#include <cstdio>using namespace std;const int M =1e6+20;int len,len1,len2;char s[M];int sa[M];//sa[i]排名i的后缀编号 int c[M];//计数数组 c[i]=j表示关键字<=i的有j个 int t1[M],t2[M]; void SA(char *s,int n,int m)//n为strlen(s)+1; m为最大字符的ascii码值{int *x=t1;//x[i]=j表示后缀i的排名 (每一轮的rank) int *y=t2;//y[p]=i;后缀i的第二关键字排名为p int i;for(i=0;i<m;i++)c[i]=0;for(i=0;i<n;i++){c[x[i]=s[i]]++;//长度为1时 x[i]的排名就为该字符ascii值}for(i=1;i<m;i++)c[i]+=c[i-1];for(i=n-1;i>=0;i--)//长度(1)的名次数组 sa[--c[x[i]]]=i;//aabaaaab 若x[i]值相同的sa靠前的小 for(int k=1;k<=n;k<<=1){int p=0;for(i=n-k;i<n;i++)y[p++]=i;//第二关键字为0的排前面 for(i=0;i<n;i++){//倍增:x+k后缀的第一关键字排名等于x后缀的第二关键字排名 if(sa[i]>=k)//只有编号大于k的才能作为第二关键字 {y[p++]=sa[i]-k;}}//通过x[],y[]计算每个后缀的长为2*k前缀的sa数组for(i=0;i<m;i++)c[i]=0;for(i=0;i<n;i++)c[x[y[i]]]++;//第二关键字排名为i的后缀y[i]的第一关键字排名//此时c[p]的值表示第一关键字排名为p的有多少个 for(i=1;i<m;i++)c[i]+=c[i-1];// 此时c[i]:第一关键字的排名为i时,小于等于它的个数 for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i];//后缀y[i]在它的2*k长度中排名为? //后缀y[i]的第一关键字排名为c[x[y[i]]] 第一关键字相同时 此时看第二关键字//y[i]中i越小 第二关键字排名就越小 后缀y[i]排名就越小 (逆推的原因)//接着更新x为长度2*k的名次数字 swap(x,y);//令y表示名次数组(rank)p=1;//此时p记录排名的不同的个数x[sa[0]]=0;for(i=1;i<n;i++){x[sa[i]]= y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?p-1:p++;//两个关键字相同则在x数组的排名是一样的 //y[sa[i]]==y[sa[i-1]],即这两个后缀的长k的第一关键字相同的情况下 //他们必定还存在第二关键需要比较 }if(p>=n) break;//字典序比较法得出 当前排名都不同时,最终排名就为此排名 m=p; //} }int rank[M],height[M];//设 height[i]=LCP(Suffix(sa[i]),Suffix(sa[i-1]))后缀排名为i和i-1的LCP //则 h[i]=height[rank[i]]= 后缀i和它前一个后缀的 LCP//h[i]>=h[i-1]-1//h[i-1]为后缀i-1和它排在它前一个的后缀k的LCP//同时去掉相同的首字符之后 后缀k+1和和后缀i的LCP为h[i]=h[i-1]-1 //因为后缀k+1和后缀i名次不一定相邻 所以若存在后缀t为后缀i相邻 则h[i]>=h[i]-1; void Height(){int i,j,k=0;for(i=0;i<len;i++)rank[sa[i]]=i;for(i=0;i<len;i++){if(k)k--;//h[i]>=h[i-1]-1;先减一int j=sa[rank[i]-1];//前一个后缀 while(s[i+k]==s[j+k])k++;height[rank[i]]=k;}} void solve(){int ans=0;for(int i=2;i<len;i++){if(height[i]>ans){//后缀sa[i]和sa[i-1]不能在同一个串中 if(sa[i-1]>=0&&sa[i-1]<len1&&sa[i]>len1&&sa[i]<len){ans=height[i];}if(sa[i]>=0&&sa[i]<len1&&sa[i-1]>len1&&sa[i-1]<len){ans=height[i];}}}printf("%d\n",ans);}int main(){scanf("%s",s);len1=strlen(s);s[len1]=1;//分隔符 scanf("%s",s+len1+1);//拼接两个粗串len2=strlen(s)-len1-1;s[len1+len2+1]=0;//末尾 len=len1+len2+2;SA(s,len,128);Height();solve();//求两个串的最长公共字串 //首先如果这两个长字符串存在某个最长的公共子串,那么该子串一定分别是这两个串的后缀的前缀. //将两个串拼接起来求最大的LCP&&两个后缀不属于同一个串 return 0;}
0 0
- poj 2774 后缀数组(模板题)
- poj 2774 后缀数组模板
- 后缀数组小模板 POJ 2774
- 后缀数组(模板题)
- POJ 2774 Long Long Message (后缀数组模板)
- poj 2774 Long Long Message 后缀数组模板
- POJ 2774 Long Long Message (后缀数组模板)
- poj 1743 -- Musical Theme (后缀数组模板题)
- Tyvj_P1860 后缀数组(后缀数组模板题)
- POJ 2774 后缀数组
- poj 2774 //后缀数组
- poj 2774 后缀数组
- poj 2774(后缀数组)
- poj 2774 后缀数组
- poj 2774 后缀数组
- POJ-2774-后缀数组
- POJ 2774 后缀数组
- poj 3294(经典后缀数组模板)
- mysql 基本命令
- hdu 迷宫城堡
- 第4周项目2 -建设“单链表”算法库
- Java内部类之静态内部类
- keepalived nopreempt 失效总结
- poj 2774 后缀数组(模板题)
- 如何设置USERENV('CLIENT_INFO')的值
- Linux结合awk的“去重”思想
- JSPatch实现原理详解:让JS调用/替换任意OC方法
- 最牛X的GCC 内联汇编
- sql之left join、right join、inner join的区别
- Ultra-QuickSort
- MySQL的binlog日志
- 一步一步制作yaffs/yaffs2根文件系统(二)