Skip to content

Instantly share code, notes, and snippets.

@libetl
Created May 1, 2016 14:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save libetl/6e063219d3987278c54c92cc4e27d954 to your computer and use it in GitHub Desktop.
Save libetl/6e063219d3987278c54c92cc4e27d954 to your computer and use it in GitHub Desktop.
Common Part Finder between two String values
package org.toilelibre.libe.util;
public class CommonPartFinder {
private static final int INDEX_NOT_FOUND = -1;
private static final String EMPTY = "";
public static class Range {
private final int aDiffStart;
private final int aDiffEnd;
private final int bDiffStart;
private final int bDiffEnd;
public Range (int aDiffStart, int aDiffEnd, int bDiffStart, int bDiffEnd) {
this.aDiffStart = aDiffStart;
this.aDiffEnd = aDiffEnd;
this.bDiffStart = bDiffStart;
this.bDiffEnd = bDiffEnd;
}
public int getaDiffStart () {
return this.aDiffStart;
}
public int getaDiffEnd () {
return this.aDiffEnd;
}
public int getbDiffStart () {
return this.bDiffStart;
}
public int getbDiffEnd () {
return this.bDiffEnd;
}
}
private static String difference (final String str1, final String str2) {
if (str1 == null) {
return str2;
}
if (str2 == null) {
return str1;
}
final int at = indexOfDifference (str1, str2);
if (at == INDEX_NOT_FOUND) {
return EMPTY;
}
return str2.substring (at);
}
private static String reverse(final String str) {
if (str == null) {
return null;
}
return new StringBuilder(str).reverse().toString();
}
private static int indexOfDifference (final CharSequence... css) {
if (css == null || css.length <= 1) {
return INDEX_NOT_FOUND;
}
boolean anyStringNull = false;
boolean allStringsNull = true;
final int arrayLen = css.length;
int shortestStrLen = Integer.MAX_VALUE;
int longestStrLen = 0;
// find the min and max string lengths; this avoids checking to make
// sure we are not exceeding the length of the string each time through
// the bottom loop.
for (int i = 0 ; i < arrayLen ; i++) {
if (css [i] == null) {
anyStringNull = true;
shortestStrLen = 0;
} else {
allStringsNull = false;
shortestStrLen = Math.min (css [i].length (), shortestStrLen);
longestStrLen = Math.max (css [i].length (), longestStrLen);
}
}
// handle lists containing all nulls or all empty strings
if (allStringsNull || longestStrLen == 0 && !anyStringNull) {
return INDEX_NOT_FOUND;
}
// handle lists containing some nulls or some empty strings
if (shortestStrLen == 0) {
return 0;
}
// find the position with the first difference across all strings
int firstDiff = INDEX_NOT_FOUND;
for (int stringPos = 0 ; stringPos < shortestStrLen ; stringPos++) {
final char comparisonChar = css [0].charAt (stringPos);
for (int arrayPos = 1 ; arrayPos < arrayLen ; arrayPos++) {
if (css [arrayPos].charAt (stringPos) != comparisonChar) {
firstDiff = stringPos;
break;
}
}
if (firstDiff != INDEX_NOT_FOUND) {
break;
}
}
if (firstDiff == -1 && shortestStrLen != longestStrLen) {
// we compared all of the characters up to the length of the
// shortest string and didn't find a match, but the string lengths
// vary, so return the length of the shortest string.
return shortestStrLen;
}
return firstDiff;
}
private static String intersection(String s1, String s2) {
for( int i = Math.min(s1.length(), s2.length()); ; i--) {
if(s2.endsWith(s1.substring(0, i))) {
return s1.substring(0, i);
}
}
}
/**
* Input : two string values
* Output :
* @param a first string
* @param b second string
* @return a range such as :
* - a.subString(0, aDiffStart).equals(b.subString(0, bDiffStart)) and
* - a.subString(aDiffEnd).equals(b.subString(bDiffEnd))
*/
public static Range commonPartRanges (String a, String b) {
String diff1End = CommonPartFinder.difference (a, b);
String diff2End = CommonPartFinder.difference (b, a);
String diff1Start = CommonPartFinder.reverse (CommonPartFinder.difference (CommonPartFinder.reverse (a), CommonPartFinder.reverse (b)));
String diff2Start = CommonPartFinder.reverse (CommonPartFinder.difference (CommonPartFinder.reverse (b), CommonPartFinder.reverse (a)));
String diff1 = CommonPartFinder.intersection (diff1End, diff1Start);
String diff2 = CommonPartFinder.intersection (diff2End, diff2Start);
return new Range (diff2Start.length () - diff2.length (),
diff2Start.length (),
diff1Start.length () - diff1.length (),
diff1Start.length ());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment