首页  编辑  

统计子串在父串中的次数

Tags: /超级猛料/String.字符串处理/   Date Created:

{ 2002.8.5 Kingron                 }

{ Source:Source string             }

{ Sub:Sub string                   }

{ Return:Count                     }

{ Ex:StrSubCount('abcdbcd','bc')=2 }

function StrSubCount ( const Source , Sub : string ): integer ;

var

 Buf               : string ;

 i                 : integer ;

 Len               : integer ;

begin

 Result := 0 ;

 Buf := Source ;

 i := Pos ( Sub , Buf );

 Len := Length ( Sub );

  while i <> 0 do

  begin

   Inc ( Result );

   Delete ( Buf , 1 , i + Len - 1 );

   i := Pos ( Sub , Buf );

  end ;

end ; { StrSubCount }

{ 下面这个函数返回SubStr在S中指定位置开始后的位置 }

{ 例如:PosExx('ab','abcabcab',3)返回4          }

function PosExx ( const substr : AnsiString ; const s : AnsiString ; const start : Integer ): Integer ;

type

 StrRec = record

   allocSiz : Longint ;

   refCnt : Longint ;

   length : Longint ;

  end ;

const

 skew               = sizeof ( StrRec );

asm

{     ->EAX     Pointer to substr               }

{       EDX     Pointer to string               }

{       ECX     Pointer to start      //cs      }

{     <-EAX     Position of substr in s or 0    }

       TEST    EAX,EAX

       JE      @@noWork

       TEST    EDX,EDX

       JE      @@stringEmpty

       TEST    ECX,ECX

       JE      @@stringEmpty

       PUSH    EBX

       PUSH    ESI

       PUSH    EDI

       MOV     ESI,EAX             { Point ESI to  }

       MOV     EDI,EDX             { Point EDI to  }

       MOV     EBX,ECX

       MOV     ECX,[EDI-skew].StrRec.length

       PUSH    EDI                 { remembers position to calculate index }

       CMP     EBX,ECX

       JG      @@fail

       MOV     EDX,[ESI-skew].StrRec.length     { EDX = bstr }

       DEC     EDX                 { EDX = Length(substr) -   }

       JS      @@fail             { < 0 ? return             }

       MOV     AL,[ESI]           { AL = first char of       }

       INC     ESI                 { Point ESI to 2'nd char of substr }

       SUB     ECX,EDX             { #positions in s to look  }

                                  { = Length(s) - Length(substr) + 1      }

       JLE     @@fail

       DEC     EBX

       SUB     ECX,EBX

       JLE     @@fail

       ADD     EDI,EBX

@@loop:

       REPNE   SCASB

       JNE     @@fail

       MOV     EBX,ECX             { save outer loop                }

       PUSH    ESI                 { save outer loop substr pointer }

       PUSH    EDI                 { save outer loop s              }

       MOV     ECX,EDX

       REPE    CMPSB

       POP     EDI                 { restore outer loop s pointer      }

       POP     ESI                 { restore outer loop substr pointer }

       JE      @@found

       MOV     ECX,EBX             { restore outer loop nter    }

       JMP     @@loop

@@fail:

       POP     EDX                 { get rid of saved s nter    }

       XOR     EAX,EAX

       JMP     @@exit

@@stringEmpty:

       XOR     EAX,EAX

       JMP     @@noWork

@@found:

       POP     EDX                 { restore pointer to first char of s    }

       MOV     EAX,EDI             { EDI points of char after match        }

       SUB     EAX,EDX             { the difference is the correct index   }

@@exit:

       POP     EDI

       POP     ESI

       POP     EBX

@@noWork:

end ;

{ PosEx返回Sub在Source中第Index次出现的位置,若出现的次数不足,返回0,若找不到,返回0         }

{ 例如:PosEx('abcdbcd','bcd',2)返回5,PosEx('abcdbcd','adb')返回0,PoxEx('abc','a',2)返回0 }

function PosEx ( const Source , Sub : string ; Index : integer ): integer ;

var

 Buf               : string ;

 i , Len , C         : integer ;

begin

 C := 0 ;

 Result := 0 ;

 Buf := Source ;

 i := Pos ( Sub , Source );

 Len := Length ( Sub );

  while i <> 0 do

  begin

   inc ( C );

   Inc ( Result , i );

   Delete ( Buf , 1 , i + Len - 1 );

   i := Pos ( Sub , Buf );

    if C >= Index then Break ;

    if i > 0 then Inc ( Result , Len - 1 );

  end ;

  if C < Index then Result := 0 ;

end ;

下面是ZsWang写的代码,效率可能要高一些:

function PosEx1 ( const Source , Sub : string ; Index : Integer = 1 ): Integer ;

var

 I , J , K , L : Integer ;

 T : string ;

begin

 Result := 0 ;

 T := Source ;

 K := 0 ;

 L := Length ( Sub );

  for I := 1 to Index do begin

   J := Pos ( Sub , T );

    if J <= 0 then Exit ;

   Delete ( T , 1 , J + L - 1 );

   Inc ( K , J + L - 1 );

  end ;

 Dec ( K , L - 1 );

 Result := K ;

end ; { PosEx1 }

下面是Dirk写的,用的实递归:

function PosN ( Substring , Mainstring : string ; n : Integer ): Integer ;

{

Function PosN get recursive - the N th position of "Substring" in

"Mainstring". Does the Mainstring not contain Substrign the result

is 0. Works with chars and strings.

}

begin

  if Pos ( substring , mainstring ) = 0 then

  begin

   posn := 0 ;

   Exit ;

  end

  else

  begin

    if n = 1 then

     posn := Pos ( substring , mainstring )

    else

    begin

     posn := Pos ( substring , mainstring ) + posn ( substring , Copy ( mainstring ,

        ( Pos ( substring , mainstring ) + 1 ), Length ( mainstring )), n - 1 );

    end ;

  end ;

end ;