/****************************/ /* 文字列探索 */ /* coded by Y.Suganuma */ /****************************/ import java.io.*; import java.util.*; public class Test { public static void main(String args[]) { long tm1 = System.currentTimeMillis(); int N = 1000201; int N1 = 5000; int N2 = 200; char pattern1[][] = new char [N1][N2]; char text1[] = new char[N]; Random rn = new Random(); // テキストと探索データの生成 int n = 0; for (int i1 = 0; i1 < N; i1++) { text1[i1] = (char)((char)(65 + 58 * rn.nextDouble())); if (n < N1 && i1 >= 2*N2 && (i1 % N2) == 0) { int k = i1 - N2 - N2 / 2 - 1; for (int i2 = 0; i2 < N2; i2++) { pattern1[n][i2] = text1[k]; k++; } if (n % 2 > 0) // 存在しないデータの作成 pattern1[n][N2/2] = '('; n++; } } String pattern[] = new String [N1]; for (int i1 = 0; i1 < N1; i1++) pattern[i1] = new String(pattern1[i1]); String text = new String(text1); long tm2 = System.currentTimeMillis(); System.out.printf("***初期設定終了: %d ms***\n", (int)(tm2-tm1)); // 検索 System.out.printf("テキスト文字数 %d 探索パターン数 %d 探索パターン文字数 %d\n", N, n, N2); // String クラスの indexOf System.out.printf("String クラスの indexOf\n"); tm1 = System.currentTimeMillis(); int hit = 0; for (int i1 = 0; i1 < n; i1++) { int sw = text.indexOf(pattern[i1]); if (sw < 0) hit++; } tm2 = System.currentTimeMillis(); System.out.printf(" 探索時間: %d ms 見つからなかったパターン数: %d\n", (int)(tm2-tm1), hit); // 単純な方法 System.out.printf("単純な方法\n"); tm1 = System.currentTimeMillis(); hit = 0; for (int i1 = 0; i1 < n; i1++) { int sw = search_s(text1, pattern1[i1]); if (sw < 0) hit++; } tm2 = System.currentTimeMillis(); System.out.printf(" 探索時間: %d ms 見つからなかったパターン数: %d\n", (int)(tm2-tm1), hit); // BM 法 System.out.printf("BM 法\n"); tm1 = System.currentTimeMillis(); hit = 0; for (int i1 = 0; i1 < n; i1++) { int sw = search_BM(text1, pattern1[i1]); if (sw < 0) hit++; } tm2 = System.currentTimeMillis(); System.out.printf(" 探索時間: %d ms 見つからなかったパターン数: %d\n", (int)(tm2-tm1), hit); } /****************************************/ /* 単純な探索 */ /* text : テキスト */ /* ptn : 探索パターン */ /* return : 発見位置(失敗したら-1) */ /****************************************/ static int search_s(char text[], char ptn[]) { int s = -1; int len = text.length - ptn.length; for (int i1 = 0; i1 < len; i1++) { int k = i1; int sw = 1; for (int i2 = 0; i2 < ptn.length; i2++) { if (ptn[i2] != text[k]) { sw = 0; break; } else k++; } if (sw > 0) { s = i1; break; } } return s; } /****************************************/ /* BM 法 */ /* text : テキスト */ /* ptn : 探索パターン */ /* return : 発見位置(失敗したら-1) */ /****************************************/ static int search_BM(char text[], char ptn[]) { int len_t = text.length; int len_p = ptn.length; // ずらし幅テーブル int step[] = new int [255]; for (int i1 = 0; i1 < 255; i1++) step[i1] = -1; for (int i1 = len_p-1; i1 >= 0; i1--) { if (step[(int)ptn[i1]] < 0) step[(int)ptn[i1]] = len_p - 1 - i1; } // 実行 int s = -1; int k = len_p - 1; while (k < len_t) { int k1 = k; int k2 = len_p - 1; int sw = 1; while (k2 >= 0) { if (ptn[k2] != text[k1]) { if (step[(int)text[k1]] < 0) // text[k1] がパターンに含まれない k += len_p; else { // text[k1] がパターンに含まれる int k3 = step[(int)text[k1]]; int k4 = len_p - k2; if (k3 > k4) k = k1 + k3; else k = k1 + k4; } sw = 0; break; } else { k1--; k2--; } } if (sw > 0) { s = k - len_p + 1; break; } } return s; } }
***初期設定終了: 62 ms*** テキスト文字数 1000201 探索パターン数 5000 探索パターン文字数 200 String クラスの indexOf 探索時間: 5520 ms 見つからなかったパターン数: 2500 単純な方法 探索時間: 11843 ms 見つからなかったパターン数: 2500 BM 法 探索時間: 576 ms 見つからなかったパターン数: 2500