泥臭い方法なんだと思うけれど、文字列同士の部分一致検索を行うロジックを書いた。
以前書いた「オノマトペマッピング」に使うアルゴリズムで、文字列をインデックスに書き換える。
理想的にはWindowを広めに取る必要があるんだろうけど、パフォーマンスどうなるんだろうね。
SiONを使う場合はJavascriptで書き直さないといけないし。
package sion.test;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.logging.Logger;
public class StringMatch2 {
private void log(String str){
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).info(str);
}
/**
* 4文字までの辞書を作成する
*
* @return
*/
private LinkedHashMap<String, ArrayList<Integer>> makeHash(String source,
int window) {
LinkedHashMap<String, ArrayList<Integer>> map = new LinkedHashMap<String, ArrayList<Integer>>();
while (window > 0) {
log("window = " + window);
for (int i = 0; i < source.length() - window + 1; i++) {
// i: index
// window: length
String sub = (source.substring(i, i + window));
// play offset list
ArrayList<Integer> list = new ArrayList<Integer>();
for (int j = 0; j < window; j++) {
list.add(i + j);
}
map.put(sub, list);
}
window--;
}
return map;
}
public static void main(String[] args) {
int window = 4;
String input = "dnsttnststdnstdndndndnsttnststdd";
String source = "ststdntnstdntnststststdnstndtntr";
ArrayList<Integer> test = new StringMatch2().replaceByStringFlagments(input, source, window);
System.out.println(test);
}
/**
* 文字列inputを、source内の文字列で置き換え、index配列表現で返す
* @param input
* @param source
* @param window 置換文字列単位の最大長
* @return
*/
private ArrayList<Integer> replaceByStringFlagments(String input, String source, int window) {
ArrayList<Integer> list = new ArrayList<Integer>();
//初期化
for (int i = 0; i < input.length(); i++) {
list.add(new Integer(-1));
}
//辞書の作成
LinkedHashMap<String, ArrayList<Integer>> makeHash = makeHash(source,
window);
//置き換え
while (window > 0) {
log("window = " + window);
for (int i = 0; i < input.length() - window + 1; i++) {
// i: index
// window: length
String sub = (input.substring(i, i + window));
log(sub);
if (makeHash.containsKey(sub)) {
log(" -- Match");
StringBuffer sb = new StringBuffer();
for (int count = 0; count < window; count++) {
sb.append("@");
}
input = input.replaceFirst(sub, sb.toString());
ArrayList<Integer> repList = makeHash.get(sub);
for (int aryIdx = 0; aryIdx < window; aryIdx++) {
list.set(i + aryIdx, repList.get(aryIdx));
}
} else {
log("");
}
}
window--;
}
return list;
}
}