HDU 2203 親和串(KMP)
阿新 • • 發佈:2017-07-16
我們 size bre -a 字符串匹配 itl cda continue ring
親和串的定義是這樣的:給定兩個字符串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。
代碼:
題目網址: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
親和串的定義是這樣的:給定兩個字符串s1和s2,如果能通過s1循環移位,使s2包含在s1中,那麽我們就說s2 是s1的親和串。
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)