POJ 3461 Oulipo(——KMP算法)
Description
The French author Georges Perec (1936–1982) once wrote a book, La disparition, without the letter 'e'. He was a member of the Oulipo group. A quote from the book:
Tout avait Pair normal, mais tout s’affirmait faux. Tout avait Fair normal, d’abord, puis surgissait l’inhumain, l’affolant. Il aurait voulu savoir où s’articulait l’association qui l’unissait au roman : stir son tapis, assaillant à tout instant son imagination, l’intuition d’un tabou, la vision d’un mal obscur, d’un quoi vacant, d’un non-dit : la vision, l’avision d’un oubli commandant tout, où s’abolissait la raison : tout avait l’air normal mais…
Perec would probably have scored high (or rather, low) in the following contest. People are asked to write a perhaps even meaningful text on some subject with as few occurrences of a given “word” as possible. Our task is to provide the jury with a program that counts these occurrences, in order to obtain a ranking of the competitors. These competitors often write very long texts with nonsense meaning; a sequence of 500,000 consecutive 'T's is not unusual. And they never use spaces.
So we want to quickly find out how often a word, i.e., a given string, occurs in a text. More formally: given the alphabet {'A', 'B', 'C', …, 'Z'} and two finite strings over that alphabet, a word W and a text T, count the number of occurrences of W in T. All the consecutive characters of W must exactly match consecutive characters of T. Occurrences may overlap.
Input
The first line of the input file contains a single number: the number of test cases to follow. Each test case has the following format:
- One line with the word W, a string over {'A', 'B', 'C', …, 'Z'}, with 1 ≤ |W| ≤ 10,000 (here |W| denotes the length of the string W).
- One line with the text T, a string over {'A', 'B', 'C', …, 'Z'}, with |W| ≤ |T| ≤ 1,000,000.
Output
For every test case in the input file, the output should contain a single number, on a single line: the number of occurrences of the word W in the text T.
Sample Input
3 BAPC BAPC AZA AZAZAZA VERDI AVERDXIVYERDIAN
Sample Output
1 3 0
题意描述:
输入两个串s1和s2
计算并输出s1在s2中能够匹配多少次
解题思路:
KMP模板题,加深对next数组的理解,主要问题是更新i或者j的位置,其实不用更新,你会发现其实到最后j是会自动返回的。
代码实现:
1 #include<stdio.h> 2 #include<string.h> 3 char s[1000010],t[10010]; 4 void get_next(char t[],int next[],int l2); 5 int kmp(char s[],char t[]); 6 int main() 7 { 8 int T; 9 scanf("%d",&T); 10 while(T--) 11 { 12 scanf("%s%s",t,s); 13 printf("%d\n",kmp(s,t)); 14 } 15 return 0; 16 } 17 int kmp(char s[],char t[]) 18 { 19 int i,j,l1,l2,c; 20 21 int next[10010];//next[]数组中存的是左上匹配串前后缀的相似度,从0到l2 22 l1=strlen(s); 23 l2=strlen(t); 24 get_next(t,next,l2); 25 26 c=0; 27 i=0; 28 j=0; 29 while(i < l1) 30 { 31 if(j==-1 || s[i] == t[j]) 32 { 33 i++; 34 j++; 35 } 36 else//少了个else 37 j=next[j]; 38 if(j==l2)//i和j均不用改动 39 c++; 40 } 41 return c; 42 } 43 void get_next(char t[],int next[],int l2) 44 { 45 int i,j; 46 i=0; 47 j=-1; 48 next[0]=-1; 49 while(i < l2) 50 { 51 if(j==-1 || t[i] == t[j]) 52 { 53 i++; 54 j++; 55 if(t[i] != t[j]) 56 next[i]=j; 57 else 58 next[i]=next[j]; 59 } 60 else//少了个else 61 j=next[j]; 62 } 63 /*for(i=0;i<=l2;i++) 64 printf("%d ",next[i]); 65 printf("\n");*/ 66 }
易错分析:
1、next数组存储的结果是错位的,正好能够被下次利用。
2、代码能力,注意细节,像少个else,找了半天错。