#include <assert.h>
#include <iostream.h>
#include <limits.h>
#include "STring.h"

inline int abs (int x)        { return (x<0)?(-x):(x); };
inline int min (int x, int y) { return (x<y)?(x):(y); };

class PatternFinder {

  public:

      // construct the pattern finder with the pattern you want
      PatternFinder ( const STring &pattern );

      ~PatternFinder( );

      // returns position of pattern within text (starting is offset into text)
      int find ( const STring &text, const int starting=0 );

  private:

      // finite automata state transition table
      struct State {
          int s[CHAR_MAX - CHAR_MIN + 1];
      };
      State *trans;

      int    pattern_length;
      int    char_base;

      // set up trans table
      void compute_transition_function( const STring &pattern );

      // 
      int &d (const int state, const char value) {
	return trans[state].s[(int(value))+char_base];
      }
};

PatternFinder::PatternFinder ( const STring &pattern ) {
 char_base = abs(CHAR_MIN); // for handling negative chars
 trans = NULL;
 compute_transition_function(pattern);
}

PatternFinder::~PatternFinder( ) {
 if(trans!=NULL) delete [] trans;
}

int PatternFinder::find ( const STring &text, const int starting ) {
 assert( starting >= 0 );

 int n = text.Get_Length();
 int q = 0;
 for(int i=starting;i<n;i++) {
  q = d(q,text[i]);
  if(q==pattern_length) return (i - pattern_length + 1);
 }
 return -1; // not found
}

void PatternFinder::compute_transition_function ( const STring &pattern ) {
 
 pattern_length = pattern.Get_Length();
 int m = pattern_length;
 trans = new State[m+1]; 

 for(int q=0; q<=m; q++) {                              // loop through all states
  STring Pq(pattern(0,q));                              // save string Pq
  for(int a=CHAR_MIN; a<=CHAR_MAX; a++) {               // loop through alphabet
   STring Pqa( Pq + char(a));                           // save string Pq + a
   int k = min(m+1,q+2);                                // 
   do { k--; } while (Pqa.Has_Suffix(pattern(0,k))==0); // loop till we have a suffix
   d(q,a) = k;                                          // save k into transition table
  }
 } 
}

main()
{

 STring pattern, text;

 cout<< "Enter Search Pattern: ";
 cin >> pattern;

 cout<< "Enter Text: ";
 cin >> text;

 cout << "Searching for: " << pattern << endl;
 cout << "Within Text:   " << text << endl;

 PatternFinder f(pattern);
 int pos = f.find(text);

 if(pos<0) {
   cout << "Pattern Not Found" << endl;
 }else{
   cout << "              " ;
   for(int i=0;i<pos;i++) cout << " ";
   cout << "*" << pattern << "*" << endl;
   cout << "Pattern Found At Position " << pos << endl;
 }

}

