1. 程式人生 > >HDU 2203 親和串(KMP)

HDU 2203 親和串(KMP)

我們 size bre -a 字符串匹配 itl cda continue ring

題目網址:http://acm.hdu.edu.cn/showproblem.php?pid=2203

題目:

親和串

Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 14720 Accepted Submission(s): 6505

Problem Description 人隨著歲數的增長是越大越聰明還是越大越笨,這是一個值得全世界科學家思考的問題,同樣的問題Eddy也一直在思考,因為他在很小的時候就知道親和串如何判斷了,但是發現,現在長大了卻不知道怎麽去判斷親和串了,於是他只好又再一次來請教聰明且樂於助人的你來解決這個問題。
親和串的定義是這樣的:給定兩個字符串s1和s2,如果能通過s1循環移位,使s2包含在s1中,那麽我們就說s2 是s1的親和串。

Input 本題有多組測試數據,每組數據的第一行包含輸入字符串s1,第二行包含輸入字符串s2,s1與s2的長度均小於100000。 Output 如果s2是s1的親和串,則輸出"yes",反之,輸出"no"。每組測試的輸出占一行。 Sample Input AABCD CDAA ASD ASDF Sample Output yes no 思路: 先算出s1和s2的長度,如果s1的長度小於s2,則直接輸出no。否則做以下操作:s1[i+len]=s1[i],len為s1的長度。即從s[len]…s[2*len-1]又是一個s1。這樣一個長度為2*len的新字符串包括了s1循環移位的所有情況,然後再在s1裏找子串s2。因為字符串的長度比較大,所以傳統的字符串匹配會超時,可以用strstr(),或者kmp。 代碼:
 1 #include <cstdio>
 2 #include <cstring>
 3 const int N=100005;
 4 char str[2*N];
 5 char sub[N];
 6 int next[N];
 7 int ok;
 8 void makeNext(){
 9     int l=strlen(sub);
10     next[0]=0;
11     for(int i=1,k=0; i<l; i++){
12         while(k>0 && sub[i]!=sub[k])    k=next[k-1];
13 if(sub[i]==sub[k]) k++; 14 next[i]=k; 15 } 16 } 17 void kmpMatch(){ 18 int lt=strlen(str); 19 int lb=strlen(sub); 20 for(int i=0,q=0; i<lt; i++){ 21 while(q>0 && sub[q]!=str[i]) q=next[q-1]; 22 if(sub[q]==str[i]) q++; 23 if(q==lb){ 24 ok=1; 25 break; 26 } 27 } 28 } 29 int main(){ 30 while(gets(str)!=NULL){ 31 gets(sub); 32 ok=0; 33 int lt=strlen(str); 34 int lb=strlen(sub); 35 if(lt<lb){ 36 printf("no\n"); 37 continue; 38 } 39 for(int i=0; i<lt; i++) str[i+lt]=str[i]; 40 str[2*lt]=\0; 41 // if(strstr(str,sub)!=NULL) printf("yes\n");直接用strstr() 42 // else printf("no\n"); 43 kmpMatch(); 44 printf("%s\n",ok?"yes":"no"); 45 } 46 return 0; 47 }

HDU 2203 親和串(KMP)