01 /****************************/
02 /* 線形探索 */
03 /* coded by Y.Suganuma */
04 /****************************/
05 #include <stdio.h>
06 #include <stdlib.h>
07 #include <time.h>
08 #include "MT.h"
09
10 int main()
11 {
12 // 初期設定
13 int s[100000], n = 0;
14 int *data = new int [5000000];
15 init_genrand((unsigned)time(NULL));
16 // データの設定
17 clock_t tm1 = clock();
18 for (int i1 = 0; i1 < 5000000; i1++) {
19 data[i1] = genrand_int31();
20 if (i1%50 == 0 && n < 100000) {
21 s[n] = data[i1];
22 n++;
23 }
24 }
25 clock_t tm2 = clock();
26 printf("保存: %d ms\n", (int)(tm2-tm1));
27 // データの探索
28 for (int i1 = 0; i1 < n; i1++) {
29 int sw = 0;
30 for (int i2 = 0; i2 < 5000000; i2++) {
31 if (data[i2] == s[i1]) {
32 sw = 1;
33 break;
34 }
35 }
36 if (sw == 0) {
37 printf("***error*** データが見つからない!\n");
38 exit(1);
39 }
40 }
41 clock_t tm3 = clock();
42 printf("探索: %d ms\n", (int)(tm3-tm2));
43
44 return 0;
45 }
保存: 46 ms 探索: 182098 ms
001 /****************************/
002 /* 二分探索 */
003 /* coded by Y.Suganuma */
004 /****************************/
005 #include <stdio.h>
006 #include <stdlib.h>
007 #include <time.h>
008 #include <algorithm>
009 #include "MT.h"
010
011 using namespace std;
012
013 /*************************/
014 /* データの比較(昇順) */
015 /* bsearch 用 */
016 /*************************/
017 int compare_n(const void *arg1, const void *arg2)
018 {
019 int *a1 = (int *)arg1;
020 int *a2 = (int *)arg2;
021 return *a1 - *a2;
022 }
023
024 /**************************************/
025 /* 二分探索( Binary Search ) */
026 /* key : 探索するキーデータ */
027 /* data : データ */
028 /* n : データ数 */
029 /* return : 1 : 見つかった */
030 /* 0 : 見つからなかった */
031 /**************************************/
032 bool search(int key, int *data, int n)
033 {
034 int sw = 0, left = 0, right = n-1, center;
035
036 if (data[right] > data[left]) {
037 while (left < right) {
038 center = (left + right) / 2;
039 if (data[center] < key)
040 left = (center < n-1) ? center + 1 : center;
041 else
042 right = center;
043 }
044 }
045 else {
046 while (left < right) {
047 center = (left + right) / 2;
048 if (data[center] > key)
049 left = (center < n-1) ? center + 1 : center;
050 else
051 right = center;
052 }
053 }
054
055 if (data[left] == key)
056 sw = 1;
057
058 return sw;
059 }
060
061 #define N 5000000
062
063 int main()
064 {
065 // 初期設定
066 int s[100000], n = 0;
067 int *data = new int [N];
068 init_genrand((unsigned)time(NULL));
069 // データの設定
070 clock_t tm1 = clock();
071 for (int i1 = 0; i1 < N; i1++) {
072 data[i1] = genrand_int31();
073 if (i1%50 == 0 && n < 100000) {
074 s[n] = data[i1];
075 n++;
076 }
077 }
078 clock_t tm2 = clock();
079 printf("保存: %d ms\n", (int)(tm2-tm1));
080 // データのソート
081 sort(data, data+N);
082 clock_t tm3 = clock();
083 printf("sort: %d ms\n", (int)(tm3-tm2));
084 // データの探索
085 for (int i1 = 0; i1 < n; i1++) {
086 int sw = search(s[i1], data, N);
087 if (sw == 0) {
088 printf("***error*** データが見つからない!\n");
089 exit(1);
090 }
091 }
092 clock_t tm4 = clock();
093 printf(" 探索: %d ms\n", (int)(tm4-tm3));
094 // データの探索(標準関数 bsearch の利用)
095 for (int i1 = 0; i1 < n; i1++) {
096 int *sw = (int *)bsearch(&s[i1], data, N, sizeof(int), compare_n);
097 if (sw == NULL) {
098 printf("***error*** データが見つからない!\n");
099 exit(1);
100 }
101 }
102 clock_t tm5 = clock();
103 printf(" 探索(bsearch): %d ms\n", (int)(tm5-tm4));
104 // データの探索(C++ 標準ライブラリ binary_search の利用)
105 for (int i1 = 0; i1 < n; i1++) {
106 bool sw = binary_search(data, data+N, s[i1]);
107 if (!sw) {
108 printf("***error*** データが見つからない!\n");
109 exit(1);
110 }
111 }
112 clock_t tm6 = clock();
113 printf(" 探索(binary_search): %d ms\n", (int)(tm6-tm5));
114
115 return 0;
116 }
保存: 30 ms sort: 402 ms 探索: 40 ms 探索(bsearch): 49 ms 探索(binary_search): 39 ms
001 /****************************/
002 /* ハッシュ法( Hash ) */
003 /* coded by Y.Suganuma */
004 /****************************/
005 #include <stdio.h>
006 #include <stdlib.h>
007 #include <string.h>
008 #include <string>
009 #include <set>
010 #include <unordered_set>
011 #include <time.h>
012 #include "MT.h"
013
014 using namespace std;
015
016 int hit = 0;
017
018 /***********************************/
019 /* クラス Hash(ハッシュテーブル) */
020 /***********************************/
021 class Hash {
022 int size; // ハッシュテーブルの大きさ
023 set <string> *table; // 衝突リスト
024
025 /*******************/
026 /* ハッシュ関数 */
027 /* s : 文字列 */
028 /*******************/
029 int hash(char *s)
030 {
031 unsigned int hash = 0;
032 int len = strlen(s);
033 for (int i1 = 0; i1 < len; i1++ ) {
034 hash = (hash << 4) + s[i1]; // 左に4ビットシフトし文字を加える
035 unsigned int g = hash & 0xf0000000; // ビット毎のAND
036 if (g != 0) {
037 hash ^= g >> 24; // 排他的論理和
038 hash ^= g;
039 }
040 }
041
042 return hash % size;
043 }
044
045 public:
046
047 /******************/
048 /* コンストラクタ */
049 /******************/
050 Hash(int sz)
051 {
052 size = sz;
053 table = new set <string> [size];
054 }
055
056 /***************************************/
057 /* データの追加 */
058 /* str : データ(文字列) */
059 /* return : =1 : 追加 */
060 /* =0 : 同じデータが存在 */
061 /***************************************/
062 int add(char *str)
063 {
064 int k = hash(str);
065 if (!(table[k].empty()))
066 hit++;
067 pair<set<string>::iterator, bool> p = table[k].insert((string)str);
068 return p.second;
069 }
070
071 /***********************************/
072 /* データの探索 */
073 /* str : データ(文字列) */
074 /* return : =1 : 見つかった */
075 /* =0 : 見つからない */
076 /***********************************/
077 int search(char *str)
078 {
079 int sw = 0;
080 int k = hash(str);
081 set<string>::iterator it = table[k].find((string)str);
082 if (it != table[k].end())
083 sw = 1;
084 return sw;
085 }
086 };
087
088 int main()
089 {
090 // 初期設定
091 int n = 0;
092 char s[100000][11];
093 Hash H(10000000);
094 init_genrand((unsigned)time(NULL));
095 // データの設定
096 printf("Hash\n");
097 clock_t tm1 = clock();
098 for (int i1 = 0; i1 < 5000000; i1++) {
099 int k = genrand_int31();
100 char st[11];
101 gcvt((double)k, 11, st);
102 st[strlen(st)-1] = '\0'; // 最後のピリオドが除かれる
103 int sw = H.add(st);
104 if (sw > 0) {
105 if (i1%50 == 0 && n < 100000) {
106 strcpy(s[n], st);
107 n++;
108 }
109 }
110 else
111 i1--;
112 }
113 clock_t tm2 = clock();
114 printf(" 保存: %d ms, 衝突回数: %d\n", (int)(tm2-tm1), hit);
115 // データの探索
116 for (int i1 = 0; i1 < n; i1++) {
117 int sw = H.search(s[i1]);
118 if (sw == 0) {
119 printf("***error*** データが見つからない!\n");
120 exit(1);
121 }
122 }
123 clock_t tm3 = clock();
124 printf(" 探索: %d ms\n", (int)(tm3-tm2));
125 // データの設定(string, unordered_set)
126 n = 0;
127 string* str = new string [100000];
128 printf("unordered_set(string)\n");
129 unordered_set<string> us;
130 for (int i1 = 0; i1 < 5000000; i1++) {
131 int k = genrand_int31();
132 char st[11];
133 gcvt((double)k, 11, st);
134 st[strlen(st)-1] = '\0'; // 最後のピリオドが除かれる
135 string sts(st);
136 pair<unordered_set<string>::iterator, bool> sw = us.insert(sts);
137 if (sw.second) {
138 if (i1%50 == 0 && n < 100000) {
139 str[n] = sts;
140 n++;
141 }
142 }
143 else
144 i1--;
145 }
146 clock_t tm4 = clock();
147 printf(" 保存(string, unordered_set): %d ms\n", (int)(tm4-tm3));
148 // データの探索(string, unordered_set)
149 for (int i1 = 0; i1 < n; i1++) {
150 unordered_set<string>::iterator it = us.find(str[i1]);
151 if (it == us.end()) {
152 printf("***error*** データが見つからない!\n");
153 exit(1);
154 }
155 }
156 clock_t tm5 = clock();
157 printf(" 探索(string, unordered_set): %d ms\n", (int)(tm5-tm4));
158 // データの設定(int, unordered_set)
159 n = 0;
160 int kk[100000];
161 printf("unordered_set(int)\n");
162 unordered_set<int> usi;
163 for (int i1 = 0; i1 < 5000000; i1++) {
164 int k = genrand_int31();
165 pair<unordered_set<int>::iterator, bool> sw = usi.insert(k);
166 if (sw.second) {
167 if (i1%50 == 0 && n < 100000) {
168 kk[n] = k;
169 n++;
170 }
171 }
172 else
173 i1--;
174 }
175 clock_t tm6 = clock();
176 printf(" 保存(int, unordered_set): %d ms\n", (int)(tm6-tm5));
177 // データの探索(int, unordered_set)
178 for (int i1 = 0; i1 < n; i1++) {
179 unordered_set<int>::iterator it = usi.find(kk[i1]);
180 if (it == usi.end()) {
181 printf("***error*** データが見つからない!\n");
182 exit(1);
183 }
184 }
185 clock_t tm7 = clock();
186 printf(" 探索(int, unordered_set): %d ms\n", (int)(tm7-tm6));
187
188 return 0;
189 }
Hash 保存: 8034 ms, 衝突回数: 1642507 探索: 35 ms unordered_set(string) 保存(string, unordered_set): 9292 ms 探索(string, unordered_set): 29 ms unordered_set(int) 保存(int, unordered_set): 2256 ms 探索(int, unordered_set): 7 ms
| a | b | c |
|---|---|---|
| 3 | 0 | 2 |






001 /****************************/
002 /* 文字列探索 */
003 /* coded by Y.Suganuma */
004 /****************************/
005 #include <stdio.h>
006 #include <string.h>
007 #include <time.h>
008 #include "MT.h"
009
010 #define N 1000201
011 #define N1 5000
012 #define N2 200
013
014 /****************************************************/
015 /* 単純な探索 */
016 /* text : テキスト */
017 /* ptn : 探索パターン */
018 /* return : 発見位置のポインタ(失敗したらNULL) */
019 /****************************************************/
020 char *search_s(char *text, char *ptn)
021 {
022 char *s = NULL;
023 int len = (int)(strlen(text) - strlen(ptn));
024 for (int i1 = 0; i1 < len; i1++) {
025 int k = i1;
026 int sw = 1;
027 for (int i2 = 0; i2 < (int)strlen(ptn); i2++) {
028 if (ptn[i2] != text[k]) {
029 sw = 0;
030 break;
031 }
032 else
033 k++;
034 }
035 if (sw > 0) {
036 s = &text[i1];
037 break;
038 }
039 }
040 return s;
041 }
042
043 /****************************************************/
044 /* BM 法 */
045 /* text : テキスト */
046 /* ptn : 探索パターン */
047 /* return : 発見位置のポインタ(失敗したらNULL) */
048 /****************************************************/
049 char *search_BM(char *text, char *ptn)
050 {
051 int len_t = (int)strlen(text);
052 int len_p = (int)strlen(ptn);
053 // ずらし幅テーブル
054 int step[255];
055 for (int i1 = 0; i1 < 255; i1++)
056 step[i1] = -1;
057 for (int i1 = len_p-1; i1 >= 0; i1--) {
058 if (step[(int)ptn[i1]] < 0)
059 step[(int)ptn[i1]] = len_p - 1 - i1;
060 }
061 // 実行
062 char *s = NULL;
063 int k = len_p - 1;
064 while (k < len_t) {
065 int k1 = k;
066 int k2 = len_p - 1;
067 int sw = 1;
068 while (k2 >= 0) {
069 if (ptn[k2] != text[k1]) {
070 if (step[(int)text[k1]] < 0) // text[k1] がパターンに含まれない
071 k += len_p;
072 else { // text[k1] がパターンに含まれる
073 int k3 = step[(int)text[k1]];
074 int k4 = len_p - k2;
075 if (k3 > k4)
076 k = k1 + k3;
077 else
078 k = k1 + k4;
079 }
080 sw = 0;
081 break;
082 }
083 else {
084 k1--;
085 k2--;
086 }
087 }
088 if (sw > 0) {
089 s = &text[k-len_p+1];
090 break;
091 }
092 }
093 return s;
094 }
095
096 /****************/
097 /* main program */
098 /****************/
099 int main()
100 {
101 clock_t tm1 = clock();
102 char **pattern = new char *[N1];
103 for (int i1 = 0; i1 < N1; i1++)
104 pattern[i1] = new char[N2+1];
105 char *text = new char[N+1];
106
107 init_genrand((unsigned)time(NULL));
108 // テキストと探索データの生成
109 int n = 0;
110 for (int i1 = 0; i1 < N; i1++) {
111 text[i1] = (char)(65 + 58 * genrand_real3());
112 if (n < N1 && i1 >= 2*N2 && (i1 % N2) == 0) {
113 int k = i1 - N2 - N2 / 2 - 1;
114 for (int i2 = 0; i2 < N2; i2++) {
115 pattern[n][i2] = text[k];
116 k++;
117 }
118 pattern[n][N2] = '\0';
119 if (n % 2 > 0) // 存在しないデータの作成
120 pattern[n][N2/2] = '(';
121 n++;
122 }
123 }
124 text[N] = '\0';
125 clock_t tm2 = clock();
126 printf("***初期設定終了: %d ms***\n", (int)(tm2-tm1));
127 // 検索
128 printf("テキスト文字数 %d 探索パターン数 %d 探索パターン文字数 %d\n", N, n, N2);
129 // 標準関数 strstr
130 printf("標準関数 strstr\n");
131 tm1 = clock();
132 int hit = 0;
133 for (int i1 = 0; i1 < n; i1++) {
134 char *str = strstr(text, pattern[i1]);
135 if (str == NULL)
136 hit++;
137 }
138 tm2 = clock();
139 printf(" 探索時間: %d ms 見つからなかったパターン数: %d\n", (int)(tm2-tm1), hit);
140 // 単純な方法
141 printf("単純な方法\n");
142 tm1 = clock();
143 hit = 0;
144 for (int i1 = 0; i1 < n; i1++) {
145 char *str = search_s(text, pattern[i1]);
146 if (str == NULL)
147 hit++;
148 }
149 tm2 = clock();
150 printf(" 探索時間: %d ms 見つからなかったパターン数: %d\n", (int)(tm2-tm1), hit);
151 // BM 法
152 printf("BM 法\n");
153 tm1 = clock();
154 hit = 0;
155 for (int i1 = 0; i1 < n; i1++) {
156 char *str = search_BM(text, pattern[i1]);
157 if (str == NULL)
158 hit++;
159 }
160 tm2 = clock();
161 printf(" 探索時間: %d ms 見つからなかったパターン数: %d\n", (int)(tm2-tm1), hit);
162
163 return 0;
164 }
***初期設定終了: 24 ms*** テキスト文字数 1000201 探索パターン数 5000 探索パターン文字数 200 標準関数 strstr 探索時間: 3062 ms 見つからなかったパターン数: 2500 単純な方法 探索時間: 231324 ms 見つからなかったパターン数: 2500 BM 法 探索時間: 1374 ms 見つからなかったパターン数: 2500
C++ の string を使用した場合
01 /****************************/
02 /* 文字列探索(C++のstring) */
03 /* coded by Y.Suganuma */
04 /****************************/
05 #include <time.h>
06 #include <iostream>
07 #include <string>
08 #include "MT.h"
09
10 #define N 1000201
11 #define N1 5000
12 #define N2 200
13
14 using namespace std;
15
16 /****************/
17 /* main program */
18 /****************/
19 int main()
20 {
21 clock_t tm1 = clock();
22 string pattern[N1];
23 string text = "";
24
25 init_genrand((unsigned)time(NULL));
26 // テキストと探索データの生成
27 int n = 0;
28 for (int i1 = 0; i1 < N; i1++) {
29 text += (char)(65 + 58 * genrand_real3());
30 if (n < N1 && i1 >= 2*N2 && (i1 % N2) == 0) {
31 int k = i1 - N2 - N2 / 2 - 1;
32 pattern[n] = text.substr(k, N2);
33 if (n % 2 > 0) // 存在しないデータの作成
34 pattern[n][N2/2] = '(';
35 n++;
36 }
37 }
38 clock_t tm2 = clock();
39 printf("***初期設定終了: %d ms***\n", (int)(tm2-tm1));
40 // 検索( C++ string の find )
41 printf("テキスト文字数 %d 探索パターン数 %d 探索パターン文字数 %d\n", N, n, N2);
42 printf("C++ string の find\n");
43 tm1 = clock();
44 int hit = 0;
45 for (int i1 = 0; i1 < n; i1++) {
46 int k = text.find(pattern[i1]);
47 if (k < 0)
48 hit++;
49 }
50 tm2 = clock();
51 printf(" 探索時間: %d ms 見つからなかったパターン数: %d\n", (int)(tm2-tm1), hit);
52
53 return 0;
54 }
***初期設定終了: 62 ms*** テキスト文字数 1000201 探索パターン数 5000 探索パターン文字数 200 C++ string の find 探索時間: 71004 ms 見つからなかったパターン数: 2500
| 講義内容目次 | 菅沼ホーム | 前ページ | 次ページ |