Onomappingアルゴリズム(Java)

泥臭い方法なんだと思うけれど、文字列同士の部分一致検索を行うロジックを書いた。 以前書いた「オノマトペマッピング」に使うアルゴリズムで、文字列をインデックスに書き換える。

理想的には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;
}

}