/*
 *  HammingDynamicProgramming.h
 *
 *  Created on: 1.5.2018
 *      Author: Tomas Capek
 */

#ifndef _HAMMING_DYNAMIC_PROGRAMMING_H__
#define _HAMMING_DYNAMIC_PROGRAMMING_H__

#include <string/LinearString.h>

namespace stringology {

namespace simulations {

class HammingDynamicProgramming {
public:
    template <class SymbolType>
    static ext::vector<ext::vector<unsigned int>> compute_table(const string::LinearString<SymbolType> & text, const string::LinearString<SymbolType> & pattern, unsigned int errors);

    template <class SymbolType>
    static ext::set<unsigned int> search(const string::LinearString<SymbolType> & text, const string::LinearString<SymbolType> & pattern, unsigned int errors);

};

template <class SymbolType>
ext::vector<ext::vector<unsigned int>> HammingDynamicProgramming::compute_table(const string::LinearString<SymbolType> & text, const string::LinearString<SymbolType> & pattern, unsigned int errors) {
  ext::vector< ext::vector <unsigned int> > table =
    ext::vector<ext::vector<unsigned int> > (
      pattern.getContent().size() + 1,
      ext::vector<unsigned int>(text.getContent().size() + 1, 0)
    );

  for(unsigned int j=1; j<=pattern.getContent().size(); j++) {
    table[j][0] = errors + 1;
  }

  for(unsigned int i = 1; i<=text.getContent().size(); i++) {
    for(unsigned int j = 1; j<=pattern.getContent().size(); j++) {
      if (pattern.getContent()[j-1] == text.getContent()[i-1]) {
        table[j][i] = table[j-1][i-1];
      } else {
        table[j][i] = table[j-1][i-1] + 1;
      }
    }
  }

  return table;
}

template <class SymbolType>
ext::set<unsigned int> HammingDynamicProgramming::search(const string::LinearString<SymbolType> & text, const string::LinearString<SymbolType> & pattern, unsigned int errors) {
  auto table = HammingDynamicProgramming::compute_table(text, pattern, errors);

  ext::set<unsigned int> result;

  for(unsigned int i=1; i<=text.getContent().size(); i++) {
    if (table[pattern.getContent().size()][i] <= errors) {
      result.insert(i);
    }
  }

  return result;
}



} // namespace simulations

} // namespace stringology

#endif /* _HAMMING_DYNAMIC_PROGRAMMING_H__ */
