醫學研究者最近發現了某些新病毒,經過對這些病毒的分析,得知他們的DNA序列都是環狀的。如今研究者已收集了大量的病毒DNA和人的DNA數據,想快速檢測出這些人是否感染了相應的病毒。爲了方便研究,研究者將人的DNA和病毒DNA均表示成由一些字母組成的字符串序列,而後檢測某種病毒DNA序列是否在患者的DNA序列中出現過,若是出現過,這此人感染了該病毒,不然沒有感染。例如,假設病毒的DNA序列爲baa,患者1的DNA序列爲aaabbba,則感染。患者2的DNA序列爲babbba,則未感染。(注意:人的DNA序列是線性的,而病毒的DNA序列是環狀的)。ios
研究者將待檢測的數據保存在一個文本文件中,文件格式和內容規定以下:文件有num+1行,第一行有一個整數num,表示有num個待檢測的任務(num<=300)。接下來每行i(2<=i<=num+1)對應一個任務,每行有兩個數據,用空格分隔,第一個數據表示病毒的DNA序列(長度<=6000),第二個數據表示人的DNA序列(長度<=10000)。算法
要求將檢測結果輸出到文件中,文件中包括num行,每行有三個數據,用空格分隔,前兩個數據分別表示輸入文件中對應病毒的DNA序列和人的DNA序列,若是該人感染了對應的病毒,該行第三個數據則爲「YES」,不然爲「NO」。 數組
思路:我直接採用的kmp算法,這能有效改善時間複雜度。考慮到病毒基因是環狀的,因此弄了個循環來更新匹配數組的值,設置一個標記,用來判斷是否匹配。注意要將匹配串清零,以防出錯。函數
注意:有些讓用BF來寫,本文再也不給出代碼,能夠參考代碼寫出一個BF函數便可。spa
#include <iostream> #include<cstring> #include<cstdio> using namespace std; char str[12005],pat[12005],pat1[12005];//pat爲模式串,str爲主串 int Next[12005]; //Next[x]下標x表示匹配失敗處字符下標 //模式串pat的前綴與x位置的後綴的最大匹配字符個數-1 void GetNext(char *pat) { int LenPat = strlen(pat); int i = 0,j = -1; Next[0] = -1; while(i < LenPat) { if(j == -1 || pat[i] == pat[j]) { i++,j++; Next[i] = j; } else j = Next[j]; } } int KMP() { int LenStr = strlen(str); int LenPat = strlen(pat); GetNext(pat); int i = 0,j = 0; while(i < LenStr) { if(j == -1 || str[i] == pat[j]) i++,j++; else j = Next[j]; if(j == LenPat) return 1; } return -1;//沒找到匹配位置 } int main() { //freopen("輸入文件夾名字","r",stdin); 從文件讀取數據 //freopen("輸出文件夾名字","w",stdout); 輸出重定向 int n; scanf("%d",&n); while(n--) { scanf("%s%s",pat1,str); char s[6005]; memset(pat,'\0',sizeof(pat));//每次將pat數組清零 bool flag=false; strcpy(s,pat1); int len = strlen(s); strcat(pat1,s); for(int i=0;i<=len;++i) { for(int j=0;j<len;++j) { pat[j]=pat1[i+j]; } //memcpy(pat,pat1+i,len); if(KMP()==1) { printf("Yes\n"); flag=true; break; } } if(!flag) printf("No\n"); } return 0; }
結果檢測code