8#ifndef KOMPAREDIFF2_LEVENSHTEINTABLE_H
9#define KOMPAREDIFF2_LEVENSHTEINTABLE_H
29template<
class SequencePair>
41 int getContent(
unsigned int posX,
unsigned int posY)
const;
42 int setContent(
unsigned int posX,
unsigned int posY,
int value);
43 bool setSize(
unsigned int width,
unsigned int height);
45 unsigned int width()
const
49 unsigned int height()
const
63 void createListsOfMarkers();
64 int chooseRoute(
int c1,
int c2,
int c3,
int current);
67 unsigned int m_width = 256;
68 unsigned int m_height = 256;
70 std::vector<unsigned int> m_table;
71 std::unique_ptr<SequencePair> m_sequences;
74template<
class SequencePair>
76 : m_size(m_height * m_width)
81template<
class SequencePair>
82LevenshteinTable<SequencePair>::LevenshteinTable(
unsigned int width,
unsigned int height)
85 , m_size(m_width * m_height)
90template<
class SequencePair>
91int LevenshteinTable<SequencePair>::getContent(
unsigned int posX,
unsigned int posY)
const
94 return m_table[posY * m_width + posX];
97template<
class SequencePair>
98int LevenshteinTable<SequencePair>::setContent(
unsigned int posX,
unsigned int posY,
int value)
100 m_table[posY * m_width + posX] = value;
105template<
class SequencePair>
106bool LevenshteinTable<SequencePair>::setSize(
unsigned int width,
unsigned int height)
109 if (((width) * (height)) > (256 * 256 * 256))
112 if (((width) * (height)) > m_size) {
113 m_size = width * height;
114 m_table.resize(m_size);
123template<
class SequencePair>
126 for (
unsigned int i = 0; i < m_height; ++i) {
127 for (
unsigned int j = 0; j < m_width; ++j) {
129 std::cout << getContent(j, i);
131 std::cout << std::endl;
135template<
class SequencePair>
138 m_sequences.reset(sequences);
139 unsigned int m = m_sequences->lengthFirst();
140 unsigned int n = m_sequences->lengthSecond();
149 for (i = 0; i < m; ++i)
152 for (j = 0; j < n; ++j)
155 int cost = 0, north = 0, west = 0, northwest = 0;
158 for (j = 1; j < n; ++j) {
159 for (i = 1; i < m; ++i) {
160 if (m_sequences->equal(i, j))
163 cost = SequencePair::allowReplace ? 1 : 2;
165 north = getContent(i, j - 1) + 1;
166 west = getContent(i - 1, j) + 1;
167 northwest = getContent(i - 1, j - 1) + cost;
169 setContent(i, j, qMin(north, qMin(west, northwest)));
173 return getContent(m - 1, n - 1);
176template<
class SequencePair>
181 if (c2 <= c1 && c2 <= c3) {
182 if (SequencePair::allowReplace || (c2 == current)) {
187 if (c3 <= c2 && c3 <= c1)
193template<
class SequencePair>
194void LevenshteinTable<SequencePair>::createListsOfMarkers()
200 unsigned int x = m_width - 1;
201 unsigned int y = m_height - 1;
203 unsigned int difference = getContent(x, y);
208 if (!m_sequences->needFineGrainedOutput(difference)) {
209 m_sequences->prependFirst(
new Marker(Marker::End, x));
210 m_sequences->prependFirst(
new Marker(Marker::Start, 0));
211 m_sequences->prependSecond(
new Marker(Marker::End, y));
212 m_sequences->prependSecond(
new Marker(Marker::Start, 0));
218 int n, nw, w, direction, currentValue;
219 while (x > 0 && y > 0) {
220 currentValue = getContent(x, y);
222 n = getContent(x, y - 1);
223 w = getContent(x - 1, y);
224 nw = getContent(x - 1, y - 1);
225 direction = chooseRoute(n, nw, w, currentValue);
232 if (!m_sequences->markerListSecond().isEmpty())
233 c = m_sequences->markerListSecond().first();
237 if (c && c->type() == Marker::End) {
239 if (n == currentValue)
240 m_sequences->prependSecond(
new Marker(Marker::Start, y));
244 if (n < currentValue)
245 m_sequences->prependSecond(
new Marker(Marker::End, y));
250 m_sequences->prependSecond(
new Marker(Marker::Start, 0));
257 if (!m_sequences->markerListSecond().isEmpty())
258 c = m_sequences->markerListSecond().first();
262 if (c && c->type() == Marker::End) {
264 if (nw == currentValue)
265 m_sequences->prependSecond(
new Marker(Marker::Start, y));
269 if (nw < currentValue)
270 m_sequences->prependSecond(
new Marker(Marker::End, y));
273 if (!m_sequences->markerListFirst().isEmpty())
274 c = m_sequences->markerListFirst().first();
278 if (c && c->type() == Marker::End) {
280 if (nw == currentValue)
281 m_sequences->prependFirst(
new Marker(Marker::Start, x));
285 if (nw < currentValue)
286 m_sequences->prependFirst(
new Marker(Marker::End, x));
296 if (!m_sequences->markerListFirst().isEmpty())
297 c = m_sequences->markerListFirst().first();
301 if (c && c->type() == Marker::End) {
303 if (w == currentValue)
304 m_sequences->prependFirst(
new Marker(Marker::Start, x));
308 if (w < currentValue)
309 m_sequences->prependFirst(
new Marker(Marker::End, x));
314 m_sequences->prependFirst(
new Marker(Marker::Start, 0));
322 m_sequences->prependFirst(
new Marker(Marker::End, x));
323 m_sequences->prependFirst(
new Marker(Marker::Start, 0));
327 m_sequences->prependSecond(
new Marker(Marker::End, y));
328 m_sequences->prependSecond(
new Marker(Marker::Start, 0));
Computes the Levenshtein distance between two sequences.
void dumpLevenshteinTable()
Debug method to check if the table is properly filled.
unsigned int createTable(SequencePair *sequences)
This calculates the levenshtein distance of 2 sequences.