如何有效地检查字符串是否包含少数子字符串之一?

时间:2017-12-07 17:10:36

标签: delphi delphi-7

如何有效地检查字符串是否包含少数子字符串之一? 假设我有一个字符串:

`Hi there, <B>my</B> name is Joe <DIV>.</DIV> Hello world. &nbsp;`

如何检查字符串是否包含<B> <DIV> &nbsp;

我可以做一个简单的事情:

Result := (Pos('<B>', S) > 0) or 
          (Pos('<DIV>', S) > 0) or 
          (Pos('&nbsp;', S) > 0);

但这似乎是非常低效的,因为它使N(在最坏的情况下)通过并且我的字符串相当大。

2 个答案:

答案 0 :(得分:2)

这是我的解决方案,感谢David Heffernan的评论:

function StringContainsAny(const S: string; const AnyOf: array of string): Boolean;
var
  CurrChr, C: PChar;
  I, L, H: Integer;
begin
  Result := False;
  CurrChr := PChar(S);
  while CurrChr^ <> #0 do
  begin
    H := High(AnyOf);
    for I := 0 to H do
    begin
      L := 0;
      C := PChar(AnyOf[I]);
      while C^ <> #0 do
      begin
        if C^ = CurrChr^ then
          Inc(L)
        else
          Break;
        Inc(C);
        Inc(CurrChr);
        if CurrChr^ = #0 then // end of S string
        begin
          Result := (C^ = #0);
          if Result or (not Result and (I = H)) then // match or last AnyOf
            Exit;
        end;
      end;
      if C^ = #0 then // match
      begin
        Result := True;
        Exit;
      end
      else
        Dec(CurrChr, L);
    end;
    Inc(CurrChr);
  end;
end;

我不确定它是否完美。

修改 我能说什么?你知道他们对假设的看法...... 实际测试后,似乎使用Pos()

function StringContainsAny(const S: string; const AnyOf: array of string): Boolean;
var
  I: Integer;
begin
  for I := 0 to High(AnyOf) do
  begin
    if Pos(AnyOf[I], S) <> 0 then
    begin
      Result := True;
      Exit;
    end;
  end;
  Result := False;
end;

比我的解决方案和@Green_Wizard解决方案更快!他们用Pos功能做得很好!

答案 1 :(得分:2)

稍微好一点的版本:

function StringContainsAny(const S: string; const AnyOf: array of string): Boolean;
var
  CurrChr, C: PChar;
  i, j, Ln: Integer;
begin
  for i := 1 to Length(S) do
  begin
    CurrChr := @S[i];
    for j := 0 to High(AnyOf) do
    begin
      C := @AnyOf[j][1]; // assume that no empty strings
      if C^ <> CurrChr^ then
        Continue;

      Ln := Length(AnyOf[j]);
      if (Length(S) + 1 - i) < Ln then // check bounds
        Continue;

      if CompareMem(C, CurrChr, Ln * SizeOf(C^)) then
        Exit(True);
    end;
  end;

  Exit(False);
end;

您还可以构建一些停止符号表并提高速度。这是一个复杂的主题,所以我建议你阅读,例如,预订Bill Smyth "Computing Patterns in Strings"