nyoj 题目5 Binary String Matching
Binary String Matching
时间限制:3000 ms | 内存限制:65535 KB
难度:3
- 描述
- Given two strings A and B, whose alphabet consist only ‘0’ and ‘1’. Your task is only to tell how many times does A appear as a substring of B? For example, the text string B is ‘1001110110’ while the pattern string A is ‘11’, you should output 3, because the pattern A appeared at the posit
- 输入
- The first line consist only one integer N, indicates N cases follows. In each case, there are two lines, the first line gives the string A, length (A) <= 10, and the second line gives the string B, length (B) <= 1000. And it is guaranteed that B is always longer than A.
- 输出
- For each case, output a single line consist a single integer, tells how many times do B appears as a substring of A.
- 样例输入
-
3 11 1001110110 101 110010010010001 1010 110100010101011
- 样例输出
-
3 0 3
此题第一感觉就是用KMP算法,代码如下1 #include <cstdio> 2 #include <cstring> 3 4 char a[12]; 5 char b[1002]; 6 int next[12]; 7 8 void getNext() { 9 next[0] = -1; 10 int len = strlen(a); 11 int i = 0,j = -1; 12 while(i < len) { 13 if(j == -1 || a[i] == a[j]) { 14 i++,j++; 15 next[i] = j; 16 } 17 else { 18 j = next[j]; 19 } 20 } 21 } 22 23 int calCnt() { 24 int at = 0; 25 int bt = 0; 26 int ans = 0; 27 int lena = strlen(a); 28 int lenb = strlen(b); 29 while(bt < lenb) { 30 if(at == -1 || a[at] == b[bt]) { 31 at++; 32 bt++; 33 if(at == lena) { 34 ans++; 35 at = next[lena]; 36 } 37 continue; 38 } 39 if(a[at] != b[bt]) { 40 at = next[at]; 41 } 42 43 } 44 return ans; 45 } 46 47 int main(int argc, char const *argv[]) 48 { 49 int n; 50 while(scanf("%d",&n) != EOF) { 51 while(n--) { 52 scanf("%s",a); 53 scanf("%s",b); 54 getNext(); 55 int ans = calCnt(); 56 printf("%d\n", ans); 57 } 58 } 59 return 0; 60 }
此算法第一要求出next数组。而求next数组的过程本身也是一个自己和自己匹配的过程。此处用i不断前进,j不断返回,用作匹配。
计数时是新的匹配过程。和求next数组的过程神似。
若求nextval数组可能会更快些,代码如下
1 #include <cstdio> 2 #include <cstring> 3 4 char a[12]; 5 char b[1002]; 6 int nextval[12]; 7 8 void getnextval() { 9 nextval[0] = -1; 10 int len = strlen(a); 11 int i = 0,j = -1; 12 while(i < len) { 13 if(j == -1 || a[i] == a[j]) { 14 i++,j++; 15 if(i < len && a[i] == a[j]) { 16 nextval[i] = nextval[j]; 17 } 18 else { 19 nextval[i] = j; 20 } 21 22 } 23 else { 24 j = nextval[j]; 25 } 26 } 27 } 28 29 int calCnt() { 30 int at = 0; 31 int bt = 0; 32 int ans = 0; 33 int lena = strlen(a); 34 int lenb = strlen(b); 35 while(bt < lenb) { 36 if(at == -1 || a[at] == b[bt]) { 37 at++; 38 bt++; 39 if(at == lena) { 40 ans++; 41 at = nextval[lena]; 42 } 43 continue; 44 } 45 if(a[at] != b[bt]) { 46 at = nextval[at]; 47 } 48 49 } 50 return ans; 51 } 52 53 int main(int argc, char const *argv[]) 54 { 55 int n; 56 while(scanf("%d",&n) != EOF) { 57 while(n--) { 58 scanf("%s",a); 59 scanf("%s",b); 60 getnextval(); 61 int ans = calCnt(); 62 printf("%d\n", ans); 63 } 64 } 65 return 0; 66 }
要注意15行的条件。但实际运行好像并没有更快。
今天偶然发现nyoj可以查看优秀的代码,这一点简直完爆其他oj,看到这样一种非常取巧的办法
1 #include <iostream> 2 #include <string> 3 using namespace std; 4 5 int main(int argc, char const *argv[]) 6 { 7 string s1,s2; 8 int n; 9 cin >> n; 10 11 while(n--) { 12 cin >> s1; 13 cin >> s2; 14 size_t m = s2.find(s1,0); 15 int ans = 0; 16 while(m != string::npos) { 17 ans++; 18 m = s2.find(s1,m+1); 19 } 20 cout << ans << endl; 21 } 22 23 return 0; 24 }