All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.almondtools.rexlex.stringsearch.KnuthMorrisPratt Maven / Gradle / Ivy

package com.almondtools.rexlex.stringsearch;

import java.util.ArrayList;
import java.util.List;

import com.almondtools.rexlex.io.CharProvider;

public class KnuthMorrisPratt implements StringSearchAlgorithm {

	private char[] pattern;
	private int patternLength;
	private int[] next;

	public KnuthMorrisPratt(String pattern) {
		this.pattern = pattern.toCharArray();
		this.patternLength = this.pattern.length;
		this.next = computeNext(this.pattern);
	}

	private int[] computeNext(char[] pattern) {
		int[] next = new int[patternLength + 1];
		next[0] = -1;

		int patternPointer = 0;
		int suffixPointer = -1;
		while (patternPointer < patternLength) {
			while (suffixPointer > -1 && pattern[patternPointer] != pattern[suffixPointer]) {
				suffixPointer = next[suffixPointer];
			}
			patternPointer++;
			suffixPointer++;
			if (patternPointer < patternLength && pattern[patternPointer] == pattern[suffixPointer]) {
				next[patternPointer] = next[suffixPointer];
			} else {
				next[patternPointer] = suffixPointer;
			}
		}
		return next;
	}

	@Override
	public int getPatternLength() {
		return patternLength;
	}

	@Override
	public StringFinder createFinder(CharProvider chars) {
		return new Finder(chars);
	}

	private class Finder implements StringFinder {

		private CharProvider chars;
		private int patternPointer;

		public Finder(CharProvider chars) {
			this.chars = chars;
			this.patternPointer = 0;
		}

		@Override
		public void skipTo(int pos) {
			chars.move(pos);
		}

		@Override
		public StringMatch findNext() {
			while (!chars.finished()) {
				char nextChar = chars.next();
				while (patternPointer > -1 && pattern[patternPointer] != nextChar) {
					patternPointer = next[patternPointer];
				}
				patternPointer++;
				if (patternPointer >= patternLength) {
					int match = patternPointer;
					patternPointer = next[patternPointer];
					return createMatch(match);
				}
			}
			return null;
		}

		@Override
		public List findAll() {
			List matches = new ArrayList();
			while (true) {
				StringMatch match = findNext();
				if (match == null) {
					return matches;
				} else {
					matches.add(match);
				}
			}
		}

		private StringMatch createMatch(int match) {
			int end = chars.current();
			int start = end - match;
			String s = chars.slice(start, end);
			return new StringMatch(start, end, s);
		}
	}

	public static class Factory implements WordSearchAlgorithmFactory {

		@Override
		public StringSearchAlgorithm of(String pattern) {
			return new KnuthMorrisPratt(pattern);
		}

	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy