package username.dynamic; /** * A collection of utilities for comparing strings. * * @author Samuel A. Rebelsky * @version 1.2 of April 2006 */ public class StringUtilsToo { // +-----------+-------------------------------------------- // | Constants | // +-----------+ /** * A value to put in caches of integers to indicate that the * cell has not been initialized. */ static final int UNINITIALIZED = -1; // +---------------+---------------------------------------- // | Static Fields | // +---------------+ /** * A count of the calls to some method. */ private static int calls; // +-----------------------------+-------------------------- // | Methods to Support Analysis | // +-----------------------------+ /** * Get the number of calls made. */ public static int getCalls() { return calls; } // getCalls /** * Reset the number of calls made. */ public static void reset() { calls = 0; } // reset() /** * Compute the "edit distance" from source to target, assuming * that each insertion costs ICOST and each deletion costs * DCOST. */ public static int ec(String source, String target, int ICOST, int DCOST) { int slen = source.length(); int tlen = target.length(); int[][] cache = new int[slen][tlen]; for (int i = 0; i < slen; i++) { for (int j = 0; j < slen; j++) { cache[i][j] = UNINITIALIZED; } // for } // for return ec(source, 0, target, 0, ICOST, DCOST, cache); } // ec(String, String, int, int) /** * Compute the "edit distance" from the portion of source starting * at spos to the portion of target starting at tpos, assuming * that each insertion costs ICOST and each deletion costs * DCOST. */ public static int ec(String source, int spos, String target, int tpos, int ICOST, int DCOST, int[][] cache) { ++calls; // Suppose source is empty. if (spos >= source.length()) { // We'll need to insert each remaining character in target. return ICOST * (target.length() - tpos); } // Suppose target is empty. else if (tpos >= target.length()) { // We'll need to delete all the characters in source. return DCOST * (source.length() - spos); } // Check the cache else if (UNINITIALIZED != cache[spos][tpos]) { return cache[spos][tpos]; } // Suppose the current character of each is the same. The cost of changing // the first to the second is the cost of changing the rest. else if (source.charAt(spos) == target.charAt(tpos)) { cache[spos][tpos] = ec(source, spos+1, target, tpos+1, ICOST, DCOST, cache); return cache[spos][tpos]; } // Whoops! The first characters differ. The cost of changing the first to // the second is either (a) the cost of inserting into the source // and then editing the rest or (b) the cost of deleting the first character of the // source and then editing the rest. else { cache[spos][tpos] = Math.min( ICOST + ec(source, spos, target, tpos+1, ICOST, DCOST, cache), DCOST + ec(source, spos+1, target, tpos, ICOST, DCOST, cache) ); return cache[spos][tpos]; } } // ec(String,int,String,int,int,int,int[][]) } // StringUtilsToo