/*
 * ReversedBoyerMooreHorspool.h
 *
 *  Created on: 5. 11. 2014
 *      Author: Jan Travnicek
 */

#ifndef _STRINGOLOGY_REVERSED_BOYER_MOORE_HORSPOOL_H_
#define _STRINGOLOGY_REVERSED_BOYER_MOORE_HORSPOOL_H_

#include <alib/set>
#include <alib/map>

#include <string/LinearString.h>

#include <string/properties/ReversedBadCharacterShiftTable.h>

namespace stringology {

namespace exact {

/**
 * Implementation of BMH for MI(E+\eps)-EVY course 2014 (Reversed)
 * To get rid of zeros in BCS table we ignore last haystack character
 */
class ReversedBoyerMooreHorspool {
public:
	/**
	 * Search for pattern in linear string.
	 * @return set set of occurences
	 */
	template < class SymbolType >
	static ext::set < unsigned > match ( const string::LinearString < SymbolType > & string, const string::LinearString < SymbolType > & pattern );

};

template < class SymbolType >
ext::set < unsigned > ReversedBoyerMooreHorspool::match ( const string::LinearString < SymbolType > & string, const string::LinearString < SymbolType > & pattern ) {
	ext::set < unsigned > occ;
	ext::map < SymbolType, size_t > bcs = string::properties::ReversedBadCharacterShiftTable::bcs ( pattern ); // NOTE: the subjects alphabet must be a subset or equal to the pattern

	int haystack_offset = string.getContent ( ).size ( ) - pattern.getContent ( ).size ( );

	while ( haystack_offset >= 0 ) {
		size_t i = 0;

		while ( i < pattern.getContent ( ).size ( ) && string.getContent ( )[haystack_offset + i] == pattern.getContent ( )[i] )
			i++;

		 // Yay, there is match!!!
		if ( i == pattern.getContent ( ).size ( ) ) occ.insert ( haystack_offset );

		haystack_offset -= bcs[string.getContent ( )[haystack_offset]];

		// common::Streams::out << haystack_offset << std::endl;
	}

	return occ;
}

} /* namespace exact */

} /* namespace stringology */

#endif /* _STRINGOLOGY_REVERSED_BOYER_MOORE_HORSPOOL_H_ */
