文字列探索

/****************************/
/* 文字列探索               */
/*      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