poj 2774 Long Long Message 后缀数组

来源:互联网 发布:mac第一次充电多久 编辑:程序博客网 时间:2024/06/08 05:57

题意:给你两串字符,要你找出在这两串字符中都出现过的最长子串的长度


分析:后缀数组傻叉题

把两个字符串合并成一个,求出height数组后找一个最大的height[i]满足i和i-1的sa值分别在两个子串内。

顺带存一波模板


代码:

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#define inf 0x7fffffff#define N 200005using namespace std;char str1[N],str2[N];int b[N],c[N],d[N],rank[N],sa[N],s[N],n,height[N];void getsa(){for (int i=1;i<=n;i++) b[s[i]]++;for (int i=1;i<=26;i++) b[i]+=b[i-1];for (int i=n;i>=1;i--) c[b[s[i]]--]=i;int t=0;for (int i=1;i<=n;i++){if (s[c[i]]!=s[c[i-1]]) t++;rank[c[i]]=t;}int j=1;while (j<=n){for (int i=0;i<=n;i++) b[i]=0;for (int i=1;i<=n;i++) b[rank[i+j]]++;for (int i=1;i<=n;i++) b[i]+=b[i-1];for (int i=n;i>=1;i--) c[b[rank[i+j]]--]=i;for (int i=0;i<=n;i++) b[i]=0;for (int i=1;i<=n;i++) b[rank[i]]++;for (int i=1;i<=n;i++) b[i]+=b[i-1];for (int i=n;i>=1;i--) d[b[rank[c[i]]]--]=c[i];t=0;for (int i=1;i<=n;i++){if (rank[d[i]]!=rank[d[i-1]]||rank[d[i]]==rank[d[i-1]]&&rank[d[i]+j]!=rank[d[i-1]+j]) t++;c[d[i]]=t;}for (int i=1;i<=n;i++) rank[i]=c[i];if (t==n) break;j*=2;}for (int i=1;i<=n;i++) sa[rank[i]]=i;}void getheight(){int k=0;for (int i=1;i<=n;i++){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(){scanf("%s",str1);int len1=strlen(str1);for (int i=0;i<len1;i++)s[++n]=str1[i]-'a'+1;scanf("%s",str2);int len2=strlen(str2);for (int i=0;i<len2;i++)s[++n]=str2[i]-'a'+1;getsa();getheight();int ans=0;for (int i=2;i<=n;i++){if (sa[i-1]<=len1&&sa[i]>len1&&height[i]>ans) ans=height[i];if (sa[i-1]>len1&&sa[i]<=len1&&height[i]>ans) ans=height[i];}printf("%d",ans);}


0 0
原创粉丝点击