Naja, dann musst du pos halt selber programmieren. Dazu würde ich erstmal den zu durchsuchenden Stream in ein Byte-Array packen, und dann das Muster darin suchen. Ich weiß grade nicht, wie fix die Indexbasierten Zugriffe beim MemoryStream sind.
In etwa so:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24:
| type TByteArray: Array of Byte;
function CheckForPattern(StartPos: Integer; Source, Pattern: TByteArray ): Boolean; begin result := true; for i := 0 to length(Pattern) do if Source[Startpos + i] <> Pattern[i] then begin result := False; break; end; end;
function SearchPattern(Source, Pattern: TByteArray): Integer; begin for i := 0 to length(Source) - length(Pattern) do begin if CheckForPattern(i, Source, Pattern) then begin result := i; break; end; end; end; |
Wenn das Suchmuster länger als ein paar Bytes ist, dann wird der Boyer-Moore-Algorithmus einen starken Geschwindigkeitsvorteil bringen, der immer deutlicher wird, wenn das Muster länger wird.
Für AnsiStrings sieht das so aus, für ein ByteArray müsste man das etwas anpassen, da bei Strings der erste Index bei 1 liegt, nicht bei 0. Ist aus meiner Diplomarbeit rauskopiert, in der Literatur heißen die Variablen t, p, m, n etc. auch immer so.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70:
| TBC_IntArray = Array[AnsiChar] of Integer;
function PreProcess_BMH_BC(p: AnsiString): TBC_IntArray; var i, m: Integer; c: Char; begin m := Length(p); for c := low(AnsiChar) to High(AnsiChar) do result[c] := m; for i := 1 to m-1 do result[p[i]] := m-i; end;
function Search_BMH_Unrolled(t,p: AnsiString): Integer; var m, n, k, j: Integer; BC: TBC_IntArray; BC_last: Integer; Large: Integer; begin m := Length(p); n := Length(t); Large := m + n + 1;
BC := PreProcess_BMH_BC(p);
BC_last := BC[p[m]]; BC[p[m]] := Large;
k := m; result := 0;
while k <= n do begin repeat k := k + BC[t[k]]; until k > n;
if k <= Large then break else k := k - Large;
j := 1; while (j < m) and (p[m-j] = t[k-j]) do inc(j);
if j=m then begin if result = 0 then result := k-j+1; k := k + 1; end else begin if t[k] = p[m] then k := k + BC_last else k := k + BC[t[k]]; end; end; end; |
Geschwindigkeit des ersten Verfahrens: Ganz grob "Länge des zu durchsuchenden Streams"
Geschwindigkeit des zweiten Verfahren: Grob geschätzt 128x schneller, wenn das Pattern länger als 128Bytes lang ist, sonst nur um den Faktor "Länge des Patterns" schneller.
We are, we were and will not be.