SPOJ 1811. POJ 2774 . 最大公共子串
2017-12-26 15:58
302 查看
Description
给出两个字符串 a,b ,求 a 和 b 的最大公共子串,字符串长度为 500000。Solution
可以用后缀数组做,将两个字符串接起来,中间用特殊的分隔符相连。求出 Height 数组之后,就可以利用 Height 数组的性质进行计算了!
对于一个 i ,如果 sa[i] 和 sa[i−1] 的位置分别属于 a 和 b ,那么 height[i] 就是合法的。
求最大值即可。时间复杂度 O(N log N) 。
Code
#include<cstdio> using namespace std; const int N=5e5+5; int n,m=27,len,ans; int sa ,rank ,r1 ,height ,tax ; int s ; inline void readln() { char ch=getchar(); while(ch<'a' || ch>'z') ch=getchar(); while(ch>='a' && ch<='z') s[++n]=ch-'a'+1,ch=getchar(); } inline void csort() { for(int i=1;i<=m;i++) tax[i]=0; for(int i=1;i<=n;i++) tax[rank[i]]++; for(int i=1;i<=m;i++) tax[i]+=tax[i-1]; for(int i=n;i;i--) sa[tax[rank[r1[i]]]--]=r1[i]; } inline void SA() { for(int i=1;i<=n;i++) rank[r1[i]=i]=s[i]; csort(); for(int j=1,p=0;j<=n;j<<=1,m=p,p=0) { for(int i=n-j+1;i<=n;i++) r1[++p]=i; for(int i=1;i<=n;i++) if(sa[i]>j) r1[++p]=sa[i]-j; csort(); for(int i=1;i<=n;i++) r1[i]=rank[i]; rank[sa[1]]=p=1; for(int i=2;i<=n;i++) rank[sa[i]]=(r1[sa[i]]==r1[sa[i-1]] && r1[sa[i]+j]==r1[sa[i-1]+j])?p:++p; } for(int i=1,lcp=0;i<=n;height[rank[i++]]=lcp) { if(lcp) lcp--; while(s[i+lcp]==s[sa[rank[i]-1]+lcp]) lcp++; } } int main() { readln(),s[len=++n]=m,readln(),SA(); for(int i=2;i<=n;i++) if(height[i]>ans && sa[i]<len^sa[i-1]<len) ans=height[i]; printf("%d",ans); return 0; }
相关文章推荐
- (Relax 后缀数组1.4)POJ 2774 Long Long Message(求两个字符串公共子串的最大长度)
- 【spoj2774】最长公共子串
- SPOJ LCS 后缀自动机找最大公共子串
- POJ 2774-Long Long Message(后缀数组+高度数组-最大公共子串长度)
- 最大子序列、最长递增子序列、最长公共子串、最长公共子序列、字符串编辑距离
- 最大子序列、最长递增子序列、最长公共子串、最长公共子序列、字符串编辑距离
- 最大子序列、最长递增子序列、最长公共子串、最长公共子序列、字符串编辑距离
- 算法之插入、归并排序,最大公共子串lcs
- LCS_最大公共子串查找算法解析
- spoj1811 Longest Common Substring(LCS)最长公共子串
- 最大公共子序列 vs 最大公共子串
- HDU1513(最大公共子串LCS+DP)
- 第八届蓝桥杯C++B组 最大公共子串
- 最大公共子串(算法)
- 【后缀数组】 POJ 2774 Long Long Message 两个字符串的最长公共子串长度
- 最大公共子串
- 求N个字符串的最大公共子串
- 【转】最大和子序列、最长递增子序列、最长公共子串、最长公共子序列、字符串编辑距离
- POJ 2217-Secretary(后缀数组+高度数组-最大公共子串长度)
- 动态规划算法求两个字符串的最大公共子串