/****************************/
/* 文字列探索 */
/* coded by Y.Suganuma */
/****************************/
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "MT.h"
#define N 1000201
#define N1 5000
#define N2 200
/****************************************************/
/* 単純な探索 */
/* text : テキスト */
/* ptn : 探索パターン */
/* return : 発見位置のポインタ(失敗したらNULL) */
/****************************************************/
char *search_s(char *text, char *ptn)
{
char *s = NULL;
int len = (int)(strlen(text) - strlen(ptn));
for (int i1 = 0; i1 < len; i1++) {
int k = i1;
int sw = 1;
for (int i2 = 0; i2 < (int)strlen(ptn); i2++) {
if (ptn[i2] != text[k]) {
sw = 0;
break;
}
else
k++;
}
if (sw > 0) {
s = &text[i1];
break;
}
}
return s;
}
/****************************************************/
/* BM 法 */
/* text : テキスト */
/* ptn : 探索パターン */
/* return : 発見位置のポインタ(失敗したらNULL) */
/****************************************************/
char *search_BM(char *text, char *ptn)
{
int len_t = (int)strlen(text);
int len_p = (int)strlen(ptn);
// ずらし幅テーブル
int step[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;
}
// 実行
char *s = NULL;
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 = &text[k-len_p+1];
break;
}
}
return s;
}
/****************/
/* main program */
/****************/
int main()
{
clock_t tm1 = clock();
char **pattern = new char *[N1];
for (int i1 = 0; i1 < N1; i1++)
pattern[i1] = new char[N2+1];
char *text = new char[N+1];
init_genrand((unsigned)time(NULL));
// テキストと探索データの生成
int n = 0;
for (int i1 = 0; i1 < N; i1++) {
text[i1] = (char)(65 + 58 * genrand_real3());
if (n < N1 && i1 >= 2*N2 && (i1 % N2) == 0) {
int k = i1 - N2 - N2 / 2 - 1;
for (int i2 = 0; i2 < N2; i2++) {
pattern[n][i2] = text[k];
k++;
}
pattern[n][N2] = '\0';
if (n % 2 > 0) // 存在しないデータの作成
pattern[n][N2/2] = '(';
n++;
}
}
text[N] = '\0';
clock_t tm2 = clock();
printf("***初期設定終了: %d ms***\n", (int)(tm2-tm1));
// 検索
printf("テキスト文字数 %d 探索パターン数 %d 探索パターン文字数 %d\n", N, n, N2);
// 標準関数 strstr
printf("標準関数 strstr\n");
tm1 = clock();
int hit = 0;
for (int i1 = 0; i1 < n; i1++) {
char *str = strstr(text, pattern[i1]);
if (str == NULL)
hit++;
}
tm2 = clock();
printf(" 探索時間: %d ms 見つからなかったパターン数: %d\n", (int)(tm2-tm1), hit);
// 単純な方法
printf("単純な方法\n");
tm1 = clock();
hit = 0;
for (int i1 = 0; i1 < n; i1++) {
char *str = search_s(text, pattern[i1]);
if (str == NULL)
hit++;
}
tm2 = clock();
printf(" 探索時間: %d ms 見つからなかったパターン数: %d\n", (int)(tm2-tm1), hit);
// BM 法
printf("BM 法\n");
tm1 = clock();
hit = 0;
for (int i1 = 0; i1 < n; i1++) {
char *str = search_BM(text, pattern[i1]);
if (str == NULL)
hit++;
}
tm2 = clock();
printf(" 探索時間: %d ms 見つからなかったパターン数: %d\n", (int)(tm2-tm1), hit);
return 0;
}
STL の string を使用した場合
/****************************/
/* 文字列探索(STLのstring) */
/* coded by Y.Suganuma */
/****************************/
#include <time.h>
#include <iostream>
#include <string>
#include "MT.h"
#define N 1000201
#define N1 5000
#define N2 200
using namespace std;
/****************/
/* main program */
/****************/
int main()
{
clock_t tm1 = clock();
string pattern[N1];
string text = "";
init_genrand((unsigned)time(NULL));
// テキストと探索データの生成
int n = 0;
for (int i1 = 0; i1 < N; i1++) {
text += (char)(65 + 58 * genrand_real3());
if (n < N1 && i1 >= 2*N2 && (i1 % N2) == 0) {
int k = i1 - N2 - N2 / 2 - 1;
pattern[n] = text.substr(k, N2);
if (n % 2 > 0) // 存在しないデータの作成
pattern[n][N2/2] = '(';
n++;
}
}
clock_t tm2 = clock();
printf("***初期設定終了: %d ms***\n", (int)(tm2-tm1));
// 検索( STL string の find )
printf("テキスト文字数 %d 探索パターン数 %d 探索パターン文字数 %d\n", N, n, N2);
printf("STL string の find\n");
tm1 = clock();
for (int i1 = 0; i1 < n; i1++)
text.find(pattern[i1]);
tm2 = clock();
printf(" 探索時間: %d ms\n", (int)(tm2-tm1));
return 0;
}