1. 程式人生 > >POJ—3461 Oulipo

POJ—3461 Oulipo

Time Limit: 1000MSMemory Limit: 65536KTotal Submissions: 50449Accepted: 20017DescriptionThe 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.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 Input3
BAPC
BAPC
AZA
AZAZAZA
VERDI
AVERDXIVYERDIANSample Output1
3
0SourceBAPC 2006 Qualification

#include<iostream>
#include<cstring>
#include<cstdio>
//用cin會超時 
using namespace std;
void get_next(char T[],int next[])
{
	 int i=0,k=-1,l=strlen(T);
	 next[0]=-1;
	 //開頭的標記為了使下一個i++的值等於0,將可能的字首和字尾相等的最大長度等於的0賦值給第i+1的位置上 
	 while(i<l)
	 {
		  if(T[i]==T[k]||k==-1)
		   next[++i]=++k;
		  //i前的字串的字尾和字首相等時的字首的下一個字元的下標 
		  else 
		   k=next[k];
		  //將k退回到下標為k上的next值,就是讓上面的if內容變成下標為i+1和下標為next【k】的判斷 
	 }
}
int KMP(char ma[],char T[],int next[])
{
	 int i=0,j=0,ans=0,l1=strlen(ma),l2=strlen(T);
	 while(i<l1&&j<l2)
	 {
		  if(ma[i]==T[j]||j==-1){i++;j++;}
		  //如果j=-1說明模式串與主串無匹配,如果相等說明i和j之前的以模式串為主的部分串是相等的
		  //所以只需要i和j都向下一位移動就行 
		  else{j=next[j];}
		  //說明模式串第j上的字元與主串上的第i上的不符,只需要將j跳到next【j】上就行了,
		  //因為在get_next時已經判斷每一個位子上如果失配需要跳到什麼位子了 
		  if(j==l2){j=next[j];ans++;}
		  //由於j跳越,會覆蓋且都有模式串的可能 
	 }
	 return ans;
}
int main()
{
	 int N,*next;
	 char ma[1000050],T[1000050];
	 scanf("%d",&N);
	 while(N--)
	 {
		  scanf("%s%s",&T,&ma);
		  next=new int[strlen(T)+1];
		  get_next(T,next);
		  cout<<KMP(ma,T,next)<<endl;
	 }
	 return 0;
}