POJ 3461 Oulipo (kmp模板题)
题目链接:POJ 3461
| Describe: |
|
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:
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:
|
| 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 |
题目大意:
若干样例,每个样例第一行给出一个单词,第二行给出一个字符串,要求输出,字符串中有多少个给定的单词。
解题思路:
比较裸的KMP,不过有一点需要根据kmp得到的next数组进行优化,在我们匹配完一次单词以后,如果所给单词从头匹配就会TLE,所以此时让下标j=next[j-1],道理很简单,同样是根据前缀后缀,公共的部分已经匹配过,不需要重复匹配。
AC代码:
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 char str[1000010]; // 输入的字符串 6 char pattern[10010]; // 输入的单词,相当于模式串 7 int next[10010]; 8 int n1,n2; // 两个串的长度 9 // 常规next数组 10 void getnext() 11 { 12 memset(next,0,sizeof(next)); 13 int i,j; 14 for(i=1,j=0; i < n2; ) 15 { 16 if(pattern[i] == pattern[j]) { 17 next[i] = next[i-1]+1; 18 i++;j++; 19 } else { 20 if(j != 0) 21 { 22 j = next[j-1]; 23 } else next[i++] = 0; 24 } 25 } 26 } 27 // 常规kmp 28 int kmp() 29 { 30 int ans = 0; // 记录出现次数 31 int i,j; 32 for(i=0,j=0; i <= n1; ) // 循环条件注意,我这种写法要有等号 33 { 34 if(j == n2) 35 { 36 j = next[j-1]; // 重点,根据next数组优化 37 ans++; 38 if(i == n1) break; 39 } 40 if(str[i] == pattern[j]) 41 { 42 i++; 43 j++; 44 } else { 45 if(j != 0) j = next[j-1]; 46 else i++; 47 } 48 } 49 return ans; 50 } 51 int main() 52 { 53 int T; 54 scanf("%d",&T); 55 while(T--) 56 { 57 scanf("%s%s",pattern,str); 58 n1 = strlen(str); 59 n2 = strlen(pattern); 60 getnext(); 61 printf("%d\n",kmp()); 62 } 63 return 0; 64 }

浙公网安备 33010602011771号