hihocoder #1415 : 后缀数组三·重复旋律3
Posted NeighThorn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hihocoder #1415 : 后缀数组三·重复旋律3相关的知识,希望对你有一定的参考价值。
#1415 : 后缀数组三·重复旋律3
Time Limit:5000ms
Case Time Limit:1000ms
Memory Limit:256MB
描述
小Hi平时的一大兴趣爱好就是演奏钢琴。我们知道一个音乐旋律被表示为长度为 N 的数构成的数列。小Hi在练习过很多曲子以后发现很多作品中的旋律有共同的部分。
旋律是一段连续的数列,如果同一段旋律在作品A和作品B中同时出现过,这段旋律就是A和B共同的部分,比如在abab 在 bababab 和 cabacababc 中都出现过。小Hi想知道两部作品的共同旋律最长是多少?
输入
共两行。一行一个仅包含小写字母的字符串。字符串长度不超过 100000。
输出
一行一个整数,表示答案。
- Sample Input
-
abcdefg abacabca
- Sample Output
- 3
分析:
把两个字符串接在一起就变成了求后缀的最长公共前缀的问题,但是由于这个前缀不能跨越两个字符串,所以我们在第一个字符串后面加上一个没有出现过的字符,再接第二个字符串,然后取所有非同一个串后缀的height的最大值...
代码:
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> //by NeighThorn using namespace std; //zhao kan fei niao mu fei hui,ying chuang hua luo lian chui di const int maxn=200000+5; int n,t,s[maxn],gs[maxn],sa[maxn],wb[maxn],wv[maxn],ran[maxn],height[maxn]; char s1[maxn],s2[maxn]; inline bool cmp(int *x,int a,int b,int l){ return x[a]==x[b]&&x[a+l]==x[b+l]; } inline void da(int *sa,int *x,int n,int m){ int i,j,p,*y=wb; for(i=0;i<m;i++) gs[i]=0; for(i=0;i<n;i++) gs[x[i]]++; for(i=1;i<m;i++) gs[i]+=gs[i-1]; for(i=n-1;~i;i--) sa[--gs[x[i]]]=i; for(j=1,p=1;p<n;j<<=1,m=p){ for(i=n-j,p=0;i<n;i++) y[p++]=i; for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j; for(i=0;i<n;i++) wv[i]=x[y[i]]; for(i=0;i<m;i++) gs[i]=0; for(i=0;i<n;i++) gs[wv[i]]++; for(i=1;i<m;i++) gs[i]+=gs[i-1]; for(i=n-1;~i;i--) sa[--gs[wv[i]]]=y[i]; p=1;swap(x,y);x[sa[0]]=0; for(i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i],sa[i-1],j)?p-1:p++; } } inline void calheight(int n){ int i,j,k=0; for(i=0;i<=n;i++) ran[sa[i]]=i; for(i=0;i<n;height[ran[i++]]=k) for(k?k--:233,j=sa[ran[i]-1];s[i+k]==s[j+k];k++); } inline int solve(int n){ int ans=0; for(int i=1;i<=n;i++) if((sa[i]<t&&sa[i-1]>t)||(sa[i]>t&&sa[i-1]<t)) ans=max(ans,height[i]); return ans; } signed main(void){ scanf("%s%s",s1,s2);t=n=strlen(s1); for(int i=0;i<n;i++) s[i]=s1[i]-‘a‘+1; s[n]=100;int lala=strlen(s2); for(int i=1;i<=lala;i++) s[i+n]=s2[i-1]-‘a‘+1;n+=lala+1; for(int i=0;i<n;i++) ran[i]=s[i]; da(sa,ran,n+1,101); calheight(n); printf("%d\n",solve(n)); return 0; }//Cap ou pas cap. Pas cap.
By NeighThorn
以上是关于hihocoder #1415 : 后缀数组三·重复旋律3的主要内容,如果未能解决你的问题,请参考以下文章
HiHocoder1415 : 后缀数组三·重复旋律3 & Poj2774:Long Long Message
hihocoder-1415 后缀数组三·重复旋律3 两个字符串的最长公共子串