回答編集履歴

1

コード例を追記

2015/11/18 03:09

投稿

yuba
yuba

スコア5568

test CHANGED
@@ -9,3 +9,139 @@
9
9
 
10
10
 
11
11
  .NET Frameworkには文字列探索のメソッド用意されてないんですよね。
12
+
13
+
14
+
15
+ --- 追記
16
+
17
+ ```c#
18
+
19
+ /// <summary>
20
+
21
+ /// byte配列の中からbyteパターンと一致する並びを検索する。
22
+
23
+ /// アルゴリズムはSunday法。
24
+
25
+ /// </summary>
26
+
27
+ /// <param name="pattern">探すパターン</param>
28
+
29
+ /// <param name="text">探索範囲となる配列</param>
30
+
31
+ /// <returns>発見した場合は開始位置、発見できなかった場合は-1</returns>
32
+
33
+ public static int SearchBytes(this byte[] text, byte[] pattern)
34
+
35
+ {
36
+
37
+ int patternLen = pattern.Length, textLen = text.Length;
38
+
39
+
40
+
41
+ // 移動量テーブルの作成
42
+
43
+ int[] qs_table = new int[byte.MaxValue + 1];
44
+
45
+
46
+
47
+ // デフォルト(パターン中に存在しないキャラクタが比較範囲の直後にあった)の場合、
48
+
49
+ // 次の比較範囲はそのキャラクタの次。(=比較範囲ずらし幅はパターン長+1)
50
+
51
+ for (int i = qs_table.Length; i-- > 0; ) qs_table[i] = patternLen + 1;
52
+
53
+
54
+
55
+ // パターンに存在するキャラクタが比較範囲の直後にあった場合、
56
+
57
+ // 次の比較範囲は、そのキャラクタとパターン中のキャラクタを一致させる位置に。
58
+
59
+ for (int n = 0; n < patternLen; ++n) qs_table[pattern[n]] = patternLen - n;
60
+
61
+
62
+
63
+ int pos;
64
+
65
+
66
+
67
+ // 移動量テーブルを用いて、文章の末尾に達しない範囲で比較を繰り返す
68
+
69
+ for (pos = 0; pos < textLen - patternLen; pos += qs_table[text[pos + patternLen]])
70
+
71
+ {
72
+
73
+ // 一致するか比較。一致したら、そのときの比較位置を返す。
74
+
75
+ if (CompareBytes(text, pos, pattern, patternLen)) return pos;
76
+
77
+ }
78
+
79
+
80
+
81
+ // 文章の末尾がまだ未比較なら、そこも比較しておく
82
+
83
+ if (pos == textLen - patternLen)
84
+
85
+ {
86
+
87
+ // 一致するか比較。一致したら、そのときの比較位置を返す。
88
+
89
+ if (CompareBytes(text, pos, pattern, patternLen)) return pos;
90
+
91
+ }
92
+
93
+
94
+
95
+ // 一致する位置はなかった。
96
+
97
+ return -1;
98
+
99
+ }
100
+
101
+
102
+
103
+ /// <summary>
104
+
105
+ /// 配列(pattern)が別の配列(text)に含まれているかを判定する。
106
+
107
+ ///
108
+
109
+ /// pos + patternLen が text.Length より大きかったり
110
+
111
+ /// pos や patternLen が 0 未満だったり、
112
+
113
+ /// needdleLen が pattern.Length より大きかったりすると
114
+
115
+ /// ArrayOutOfBoundException が発生する。
116
+
117
+ /// </summary>
118
+
119
+ /// <param name="text">この配列の pos 番目からを pattern と比較する</param>
120
+
121
+ /// <param name="pos">text のどこから比較するか</param>
122
+
123
+ /// <param name="pattern">この配列全体が、text の pos 番目からと一致しているかを判定する</param>
124
+
125
+ /// <param name="patternLen">patternのうち一致判定する長さ</param>
126
+
127
+ /// <returns></returns>
128
+
129
+ static bool CompareBytes(byte[] text, int pos, byte[] pattern, int patternLen)
130
+
131
+ {
132
+
133
+ for (int comparer = 0; comparer < patternLen; ++comparer)
134
+
135
+ {
136
+
137
+ if (text[comparer + pos] != pattern[comparer]) return false;
138
+
139
+ }
140
+
141
+ return true;
142
+
143
+ }
144
+
145
+
146
+
147
+ ```