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.
InputThe 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.
OutputFor 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
题解:
这道题就是一道模板题,但是我还是出错了T_T
1 if(k==plen-1) 2 { 3 ans++; //是用来计数的 4 k=-1; 5 i=i-plen+1+1; 6 } 7 8 我让他每次从父字符串找到这个子字符串后就让这个子字符串从头开始在父字符串的上一个匹配成功的位置之后再开始匹配 9 10 这样每次都是从头开始匹配,那我们的next数组的作用不就体会不到了吗 11 12 所以每找到一个子字符串后就利用next进行下一个的寻找
改成
1 if(k==plen-1) 2 { 3 ans++; 4 k=next[k]; 5 }
最后代码:
1 #include<stdio.h> 2 #include<string.h> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 const int maxn=1000005; 7 const int INF=0x3f3f3f3f; 8 char str[maxn],ptr[maxn]; 9 int ans; 10 void get_next(int len,int *next) 11 { 12 next[0]=-1; 13 int k=-1; 14 for(int i=1;i<=len-1;++i) 15 { 16 while(k>-1 && ptr[k+1]!=ptr[i]) 17 k=next[k]; 18 if(ptr[k+1]==ptr[i]) 19 { 20 k+=1; 21 } 22 next[i]=k; 23 } 24 } 25 void kmp(int slen,int plen) 26 { 27 int next[plen]; 28 get_next(plen,next); 29 int k=-1; 30 for(int i=0;i<slen;++i) 31 { 32 while(k>-1 && ptr[k+1]!=str[i]) 33 { 34 k=next[k]; 35 } 36 if(ptr[k+1]==str[i]) 37 { 38 k=k+1; 39 } 40 if(k==plen-1) 41 { 42 ans++; 43 k=next[k]; 44 //i=i-plen+1+1; 45 } 46 } 47 } 48 int main() 49 { 50 int t; 51 scanf("%d",&t); 52 while(t--) 53 { 54 ans=0; 55 scanf("%s%s",ptr,str); 56 int slen=strlen(str); 57 int plen=strlen(ptr); 58 kmp(slen,plen); 59 printf("%d\n",ans); 60 } 61 return 0; 62 }