如何用最快速遍历一个超大字符串,大概1M多?没有快速遍历方法,拆分字符串会很慢?

解决方案 »

  1.   

    首先你要找什么?只找找的话
    用Pos('??',Str) 就OK了
      

  2.   

    要看你怎样遍历了。
    简单的用 Pos 即可。如果复杂一些的应用,例如查找多个子串、替换子串
    可以看看《传说中世界上最快的查找和替换函数:(大富翁DreamTiger原创)》unit FastString;interfaceType
    TFastPosProc = function(
      const aSourceString, aFindString : String;
      const aSourceLen, aFindLen, StartPos : integer
    ) : integer; function __FastReplace( 
      var aSourceString : String;
      const aFindString, aReplaceString : String;
      CaseSensitive : Boolean = False) : String; function __FastPos( 
      const aSourceString, aFindString : String;
      const aSourceLen, aFindLen, StartPos : integer
      ) : integer; function __FastPosNoCase( 
      const aSourceString, aFindString : String;
      const aSourceLen, aFindLen, StartPos : integer 
      ) : integer; implementationfunction __FastPos( 
      const aSourceString, aFindString : String;
      const aSourceLen, aFindLen, StartPos : integer
      ) : integer; 
    var 
      SourceLen : integer; 
    begin 
      SourceLen := aSourceLen; 
      SourceLen := SourceLen - aFindLen; 
      if (StartPos-1) > SourceLen then begin
        Result := 0;
        Exit;
      end;
      SourceLen := SourceLen - StartPos;
      SourceLen := SourceLen +2;
      asm
        push ESI 
        push EDI 
        push EBX 
        mov EDI, aSourceString 
        add EDI, StartPos 
        Dec EDI 
        mov ESI, aFindString 
        mov ECX, SourceLen 
        Mov Al, [ESI] 
        @ScaSB: 
        Mov Ah, [EDI] 
        cmp Ah,Al 
        jne @NextChar 
        @CompareStrings: 
        mov EBX, aFindLen 
        dec EBX     Jz @EndOfMatch     @CompareNext: 
        mov Al, [ESI+EBX] 
        mov Ah, [EDI+EBX] 
        cmp Al, Ah 
        Jz @Matches 
        Mov Al, [ESI] 
        Jmp @NextChar 
        @Matches: 
        Dec EBX 
        Jnz @CompareNext     @EndOfMatch:     mov EAX, EDI 
        sub EAX, aSourceString 
        inc EAX 
        mov Result, EAX 
        jmp @TheEnd 
        @NextChar: 
        Inc EDI 
        dec ECX     jz @Result0 
        cmp ah, $80 
        jb @ScaSB 
        Inc EDI 
        Dec ECX     jnz @ScaSB     @Result0:     mov Result,0 
        @TheEnd: 
        pop EBX 
        pop EDI 
        pop ESI 
      end; 
    end;function __FastPosNoCase( 
      const aSourceString, aFindString : String;
      const aSourceLen, aFindLen, StartPos : integer
      ) : integer; 
    var
      SourceLen : integer;
    begin
      SourceLen := aSourceLen;
      SourceLen := SourceLen - aFindLen;
      if (StartPos-1) > SourceLen then begin
        Result := 0;
        Exit;
      end;
      SourceLen := SourceLen - StartPos;
      SourceLen := SourceLen +2;
      asm
        push ESI 
        push EDI 
        push EBX     mov EDI, aSourceString 
        add EDI, StartPos 
        Dec EDI 
        mov ESI, aFindString 
        mov ECX, SourceLen 
        Mov Al, [ESI]     cmp Al, $7A 
        ja @ScaSB     cmp Al, $61 
        jb @ScaSB     and Al, $df     @ScaSB: 
        Mov Ah, [EDI]     cmp Ah, $7A 
        ja @CompareChar     cmp Ah, $61 
        jb @CompareChar     and Ah, $df     @CompareChar: 
        cmp Ah,Al 
        jne @NextChar 
        @CompareStrings: 
        mov EBX, aFindLen 
        dec EBX     Jz @EndOfMatch     @CompareNext: 
        mov Al, [ESI+EBX] 
        mov Ah, [EDI+EBX]     cmp Ah, $7A 
        ja @LowerAh     cmp Al, $61 
        jb @LowerAh     and Al, $df     @LowerAh: 
        cmp Ah, $7A 
        ja @CompareChar2     cmp Ah, $61 
        jb @CompareChar2     and Ah, $df     @CompareChar2: 
        cmp Al, Ah 
        Jz @Matches 
        Mov Al, [ESI]     cmp Al, $7A 
        ja @NextChar     cmp Al, $61 
        jb @NextChar     and Al, $df 
        Jmp @NextChar 
        @Matches: 
        Dec EBX 
        Jnz @CompareNext     @EndOfMatch:     mov EAX, EDI 
        sub EAX, aSourceString 
        inc EAX 
        mov Result, EAX 
        jmp @TheEnd 
        @NextChar: 
        Inc EDI 
        dec ECX 
        jz @Result0 
        cmp ah, $80 
        jb @ScaSB 
        Inc EDI 
        Dec ECX 
        jnz @ScaSB 
        @Result0: 
        mov Result,0 
        @TheEnd: 
        pop EBX 
        pop EDI 
        pop ESI 
      end; 
    end;procedure MyMove( 
      const Source; var Dest; Count : Integer);
    asm 
      cmp ECX,0 
      Je @JustQuit 
      push ESI 
      push EDI 
      mov ESI, EAX 
      mov EDI, EDX 
      @Loop: 
      Mov AL, [ESI] 
      Inc ESI 
      mov [EDI], AL 
      Inc EDI 
      Dec ECX 
      Jnz @Loop 
      pop EDI 
      pop ESI 
      @JustQuit: 
    end;function __FastReplace( 
      var aSourceString : String;
      const aFindString, aReplaceString : String;
      CaseSensitive : Boolean = False) : String; 
    var 
      ActualResultLen, 
      CurrentPos, 
      LastPos, 
      BytesToCopy, 
      ResultLen, 
      FindLen, 
      ReplaceLen, 
      SourceLen : Integer; 
      FastPosProc : TFastPosProc; 
    begin 
      if CaseSensitive then 
        FastPosProc := __FastPos
      else
        FastPOSProc := __FastPOSNoCase;  Result := '';
      FindLen := Length(aFindString);
      ReplaceLen := Length(aReplaceString);
      SourceLen := Length(aSourceString);
      if ReplaceLen <= FindLen then
        ActualResultLen := SourceLen
      else 
        ActualResultLen := 
          SourceLen +
          (SourceLen * ReplaceLen div FindLen) +
          ReplaceLen; 
      SetLength(Result,ActualResultLen); 
      CurrentPos := 1; 
      ResultLen := 0; 
      LastPos := 1; 
      if ReplaceLen > 0 then begin 
      repeat 
        CurrentPos := 
        FastPosProc(aSourceString, aFindString, 
        SourceLen, FindLen, CurrentPos); 
        if CurrentPos = 0 then break; 
        BytesToCopy := CurrentPos-LastPos; 
        MyMove(aSourceString[LastPos], 
        Result[ResultLen+1], BytesToCopy); 
        MyMove(aReplaceString[1], 
        Result[ResultLen+1+BytesToCopy], ReplaceLen); 
        ResultLen := ResultLen + 
        BytesToCopy + ReplaceLen; 
        CurrentPos := CurrentPos + FindLen; 
        LastPos := CurrentPos; 
      until false; 
      end else begin 
        repeat 
          CurrentPos := __FastPos(aSourceString, 
          aFindString, SourceLen, FindLen, CurrentPos); 
          if CurrentPos = 0 then break; 
          BytesToCopy := CurrentPos-LastPos; 
          MyMove(aSourceString[LastPos], 
          Result[ResultLen+1], BytesToCopy); 
          ResultLen := ResultLen + 
          BytesToCopy + ReplaceLen; 
          CurrentPos := CurrentPos + FindLen; 
          LastPos := CurrentPos; 
        until false; 
      end; 
      Dec(LastPOS); 
      SetLength(Result, ResultLen + (SourceLen-LastPos)); 
      if LastPOS+1 <= SourceLen then
      MyMove(aSourceString[LastPos+1], 
      Result[ResultLen+1],SourceLen-LastPos); 
    end; end.