1. 程式人生 > >【二分+字串hs】[POI2000] 公共串

【二分+字串hs】[POI2000] 公共串

題目描述
給出幾個由小寫字母構成的單詞,求它們最長的公共子串的長度。 任務:

l 讀入單詞

l 計算最長公共子串的長度

l 輸出結果

輸入格式
檔案的第一行是整數 n,1<=n<=5,表示單詞的數量。接下來n行每行一個單詞,只由小寫字母組成,單詞的長度至少為1,最大為2000。

輸出格式
僅一行,一個整數,最長公共子串的長度。

樣例一
input

3
abcb
bca
acbc 
output

2
限制與約定
時間限制:1s1s
空間限制:256MB
T

這道題看起來十分複雜,其實就是暴力二分長度

然後在第一個串中框一個這麼長的串去其他的裡面去驗證

程式碼在此

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define MA 2011
 5 #define seed 1313131
 6 using namespace std;
 7 typedef unsigned long long ull;
 8 int n,l=1,r=0x7f7f7f7f,ans;
 9 char in[10][MA];
10 int len[10];
11 ull vv[10
][MA],se[MA]; 12 inline bool check(int lenn) 13 { 14 for(int i=1;i+lenn-1<=len[1];i++) 15 { 16 int l=i,r=i+lenn-1; 17 int yeah=0; 18 ull val=vv[1][r]-vv[1][l-1]*se[lenn]; 19 for(int j=2;j<=n;j++) 20 { 21 int kk=0; 22 for
(int k=1;k+lenn-1<=len[j];k++) 23 { 24 int ll=k,rr=k+lenn-1; 25 if(val==vv[j][rr]-vv[j][ll-1]*se[lenn]){kk=1;break;} 26 } 27 if(kk)yeah++; 28 } 29 if(yeah==n-1)return 1; 30 } 31 return 0; 32 } 33 int main() 34 { 35 scanf("%d",&n); 36 se[0]=1; 37 for(int i=1;i<MA;i++)se[i]=se[i-1]*seed; 38 for(int i=1;i<=n;i++) 39 { 40 scanf("%s",in[i]+1); 41 int ll=strlen(in[i]+1); 42 len[i]=ll,r=min(r,ll); 43 for(int j=1;j<=len[i];j++) 44 vv[i][j]=vv[i][j-1]*seed+in[i][j]; 45 } 46 while(l<=r) 47 { 48 int mid=(l+r)/2; 49 if(check(mid))l=mid+1,ans=mid; 50 else r=mid-1; 51 } 52 printf("%d\n",ans); 53 } 54 /* 55 4 56 alamakotaipsa 57 olamakotaikure 58 kotaipsa 59 ewamaswinkekotaipsa 60 */