/**
  * @file	KMPcount.java
  * @synopsis 	To compare the running time of KMP and naive string matching
  *		CONVENTION:
  *		The first index (i=0) of arrays are not used.
  *
  * @author	Chee Yap
  * @date	Apr 25, 2001 (for Basic Algorithms class)
  */

public class KMPcount {

  // Members:
	char[] T;	// This is the text
 	char[] P;	// This is pattern
	int [] fail;	// Failure function for pattern
	int counter;	// used to keep track of number of comparisons

  // Constructors:

	KMPcount(char[] p, char[] t) {
	  P = p; T = t;
	  counter = 0;
	  computeFail();
	} //

  // Methods:

	/******************************************************
	 Routine to compute the failure function 
	 ******************************************************/
	public void computeFail() {
	  // init:
		fail = new int[P.length];
		fail[1] = 0;
	  // loop:
		for (int k=2; k< fail.length; k++) {
		  int kk = fail[k-1];
		  counter++;
		  while (kk>0 && (P[kk] != P[k-1])) {
		    kk = fail[kk];
		    counter++;
		  }
		  fail[k] = 1 + kk;
		}
	} // computeFail(P)

	/******************************************************
	 THIS IS THE MAIN ROUTINE
	 ******************************************************/
	public int find(int start) {
	  // init:
		int j = start; // text index 
		int k = 1; // pattern index
	  // loop:
		while (j < T.length) {
		  if (k >= P.length) return(j - k + 1);
		  if ((T[j] == P[k]) || (k==0)) {
		    counter++;
		    j++; k++;
		  } else {
		    k = fail[k];	// k could become 0
		  }
		} // while
		counter++;
	  // Not found:
		return(-1);
	} // find()

	/******************************************************
	 prints data
	 ******************************************************/
	void output() {
	  System.out.print("> Pattern = \""); 
	  for (int i=1; i< P.length; i++) 
		System.out.print(P[i]);
	  System.out.print("\"\n> Text    = \""); 
	  for (int i=1; i< T.length; i++) 
		System.out.print(T[i]);
	  System.out.println("\"");
	} // output()


	/******************************************************
	 Main method
	 ******************************************************/
	public static void main( String[] args) {

	  // sample input with 6 keys
	  //	(the first is a dummy key)

	  // char[] p = {'0', 'o', 'u'};
	  char[] p = {'0', 'y', 'o', 'u'};
	  char[] t = {'0',
		'a', 'r', 'e', ' ', 'y', 'o', 'u', ' ',
		'a', ' ', 'y', 'o', 'u', 't', 'h', '?'};

	  // construct a KMPcount object
	  KMPcount m = new KMPcount(p, t);
	  m.output();  	// print data

	  // find all matches
	  int f = m.find(1);
	  if (f<1)
	  	System.out.println(">>  No match found");
	  else {
		while (f>=1) {
		  System.out.println(">>  Match found at position " + f);
		  f = m.find(f+1);
		}//while
	  }//else

	  System.out.println(">> NUMBER OF COMPARISONS = " + m.counter);

  	} // main

}//class KMPcount
