日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【后缀数组】【poj2774】【 Long Long Message】

發布時間:2024/9/20 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【后缀数组】【poj2774】【 Long Long Message】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題意:

求兩個串的最長連續子串。


我的想法:

? ? ? 枚舉第二個串...在第一個串的后綴數組中二分查找.

? ? ? 復雜度NlogN。最壞情況N^2


題解:

(3)height 數組:定義height[i]=suffix(SA[i-1])和suffix(SA[i])的最長公共前綴,也就是排名相鄰的兩個后綴的最長公共前綴。

(4) h[i]=height[rank[i]],也就是suffix(i)和在它前一名的后綴的最長公共前綴。

(5)LCP(i,j):對正整數i,j 定義LCP(i,j)=lcp(Suffix(SA[i]),Suffix(SA[j]),其中i,j 均為1 至n 的整數。LCP(i,j)也就是后綴數組中第i 個和第j 個后綴的最長公共前綴的長度。其中,函數lcp(u,v)=max{i|u=v},也就是從頭開始順次比較u 和v 的對應字符,對應字符持續相等的最大位置,稱為這兩個字符串的最長公共前綴。

2.2?? 幾個性質

(1)LCP(i,j)=min{height[k]|i+1≤k≤j},也就是說,計算LCP(i,j)等同于詢問一維數組height 中下標在i+1 到j 范圍內的所有元素的最小值。

(1) 最長公共子串。給定兩個字符串A 和B,求最長公共子串。

『解析』先將第二個字符串寫在第一個字符串后面,中間用一個沒有出現過的字符隔開,再求這個新的字符串的后綴數組。當suffix(sa[i-1]) 和suffix(sa[i])不是同一個字符串中的兩個后綴時,max{height[i]}才是滿足條件


..代碼 二段 有一種WA了1萬次才過 #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <ctime> #include <algorithm> #include <iostream> #include <sstream> #include <string> #define oo 0x13131313 using namespace std;/**suffix array*倍增算法 O(n*logn)*待排序數組長度為n,放在0~n-1中,在最后面補一個0*build_sa( ,n+1, );//注意是n+1;*getHeight(,n);*例如:*n = 8;*num[] = { 1, 1, 2, 1, 1, 1, 1, 2, $ };注意num最后一位為0,其他大于0*rank[] = { 4, 6, 8, 1, 2, 3, 5, 7, 0 };rank[0~n-1]為有效值,rank[n]必定為0無效值*sa[] = { 8, 3, 4, 5, 0, 6, 1, 7, 2 };sa[1~n]為有效值,sa[0]必定為n是無效值*height[]= { 0, 0, 3, 2, 3, 1, 2, 0, 1 };height[2~n]為有效值**/ const int MAXN=300000+5; char S1[MAXN],S2[MAXN]; int sa[MAXN]; int t1[MAXN],t2[MAXN],c[MAXN]; int rank[MAXN],height[MAXN]; void build_sa(int s[],int n ,int m) {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]=s[i]]++;for(int i=0;i<m;i++) c[i]+=c[i-1];for(int i=n-1;i>=0;i--) sa[--c[x[i]]]=i;for(j=1;j<=n;j<<=1){p=0;for(i=n-j;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<m;i++) c[i]=0;for(i=0;i<n;i++) c[x[y[i]]]++;for(i=0;i<m;i++) c[i]+=c[i-1];for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];swap(x,y);p=1;x[sa[0]]=0;for(i=1;i<n;i++)x[sa[i]]=(y[sa[i-1]]==y[sa[i]])&&(y[sa[i-1]+j]==y[sa[i]+j])?p-1:p++;if(p>=n) break;m=p;} } int s[MAXN]; int len1,len2,ans=0; void getHeight(int s[],int n) {int i,j,k=0;for(i=0;i<=n;i++)rank[sa[i]]=i;for(i=0;i<n;i++){if(k)k--;j=sa[rank[i]-1];while(s[i+k]==s[j+k])k++;height[rank[i]]=k;} } int main() {// freopen("a.in","r",stdin);// freopen("a.out","w",stdout);while(scanf("%s",S1)!=EOF){int ans=0;len1=strlen(S1);scanf("%s",S2);len2=strlen(S2);for(int i=0;i<len1;i++) s[i]=S1[i];s[len1]='$';for(int i=len1+1;i<=len2+len1+1;i++) s[i]=S2[i-len1-1];build_sa(s,len1+len2+2,256);getHeight(s,len1+len2+1);for(int i=2;i<=len1+len2+1;i++){int MAX=max(sa[i-1],sa[i]);int MIN=min(sa[i-1],sa[i]);if(MAX>len1&&MIN<len1){if(ans<height[i])ans=height[i];}}cout<<ans<<endl;} }
#include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <ctime> #include <algorithm> #include <iostream> #include <sstream> #include <string> #define oo 0x13131313 using namespace std;/**suffix array*倍增算法 O(n*logn)*待排序數組長度為n,放在0~n-1中,在最后面補一個0*build_sa( ,n+1, );//注意是n+1;*getHeight(,n);*例如:*n = 8;*num[] = { 1, 1, 2, 1, 1, 1, 1, 2, $ };注意num最后一位為0,其他大于0*rank[] = { 4, 6, 8, 1, 2, 3, 5, 7, 0 };rank[0~n-1]為有效值,rank[n]必定為0無效值*sa[] = { 8, 3, 4, 5, 0, 6, 1, 7, 2 };sa[1~n]為有效值,sa[0]必定為n是無效值*height[]= { 0, 0, 3, 2, 3, 1, 2, 0, 1 };height[2~n]為有效值**/ const int MAXN=300000+5; char S1[MAXN],S2[MAXN]; int sa[MAXN]; int t1[MAXN],t2[MAXN],c[MAXN]; int rank[MAXN],height[MAXN]; void build_sa(int s[],int n ,int m) {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]=s[i]]++;for(int i=0;i<m;i++) c[i]+=c[i-1];for(int i=n-1;i>=0;i--) sa[--c[x[i]]]=i;for(j=1;j<=n;j<<=1){p=0;for(i=n-j;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<m;i++) c[i]=0;for(i=0;i<n;i++) c[x[y[i]]]++;for(i=0;i<m;i++) c[i]+=c[i-1];for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];swap(x,y);p=1;x[sa[0]]=0;for(i=1;i<n;i++)x[sa[i]]=(y[sa[i-1]]==y[sa[i]])&&(y[sa[i-1]+j]==y[sa[i]+j])?p-1:p++;if(p>=n) break;m=p;} } int s[MAXN]; int len1,len2,ans=0; void getHeight(int s[],int n) {int i,j,k=0;for(i=0;i<=n;i++)rank[sa[i]]=i;for(i=0;i<n;i++){if(k)k--;j=sa[rank[i]-1];while(s[i+k]==s[j+k])k++;height[rank[i]]=k;} } int main() {//freopen("a.in","r",stdin);//freopen("a.out","w",stdout);while(scanf("%s",S1)!=EOF){int ans=0;len1=strlen(S1);scanf("%s",S2);len2=strlen(S2);for(int i=0;i<len1;i++) s[i]=S1[i];s[len1]='@';for(int i=len1+1;i<=len2+len1+1;i++) s[i]=S2[i-len1-1];build_sa(s,len1+len2+2,128);getHeight(s,len1+len2+1);for(int i=2;i<=len1+len2+1;i++){if((long long)(sa[i]-len1)*(long long)(sa[i-1]-len1)<0) //乘爆了long long WA了無數發 真是酸爽{if(ans<height[i])ans=height[i];}}cout<<ans<<endl;} }


轉載于:https://www.cnblogs.com/zy691357966/p/5480325.html

總結

以上是生活随笔為你收集整理的【后缀数组】【poj2774】【 Long Long Message】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。