DELPHI의 와일드카드 비교(5판)
저자 : 리준위
이메일: [email protected] 2003.1.5
DELPHI에는 와일드카드에 대한 기성 함수가 없다고 생각했는데 MatchesMask()를 발견했습니다. 이 기능을 발견하기 전에는 자유로운 상태와 기분이 좋을 때 이 기능을 구현하기 위해 커스텀 함수를 만들곤 했습니다.
프로그램의 알고리즘은 더 복잡합니다. 먼저 하위 문자열 끝에 '?'를 추가합니다. *'를 입력한 다음 하위 문자열을 읽고 하위 문자열의 와일드카드 문자 사이, 즉 하위 문자열의 하위 문자열을 찾은 다음 소스 문자열에서 하위 문자열에 하위 문자열이 포함되어 있는지 검색합니다. 구현하는 데는 여전히 비용이 많이 듭니다. 이 함수는 다음 기능을 구현합니다.
1. 대부분의 경우 재귀 알고리즘과 MatchesMask()보다 빠를 수 있습니다.
2. 모든 경우에 별표와 물음표의 올바른 비교를 구현했습니다. //확인하는 데 시간이 필요할 수 있습니다.
3. 중국어 지원; //별표와 물음표는 영어로 입력해야 유효합니다.
4. 대소문자 구분 선택을 지원합니다.
하위 문자열의 시작 부분과 끝 부분에 별표를 추가하는 것에는 차이가 있습니다. 이 알고리즘은 스택에서 재귀 알고리즘을 사용하여 구현한 함수와 유사할 수 있지만 실제로는 약간 다릅니다. 대부분의 경우 재귀 프로세스보다 더 빠를 수 있습니다. ? 틀림없이. 최소한 다음 추정치는 있습니다. 소스 문자열이 "1111111111"이고 하위 문자열이 "*11111112*"인 것처럼 와일드카드 비교가 부분 문자열을 찾는 데만 사용되는 경우 재귀 알고리즘 사용의 시간 복잡도는 O(N*M ) 하지만 나는 이렇게 썼다. 그러면 이 함수는 대략 POS() 함수를 여러 번 호출하는 시간 복잡도로 단순화됩니다. 아마도 DELPHI의 POS()는 아래의 "Knut-Morris-Pratt(KMP) 알고리즘" O(N+M)으로 상상할 수 있습니다. . 재귀 알고리즘과의 속도 비교는 횟수가 적기 때문에 명확하지 않습니다. 소스 문자열에 100개의 연속된 1이 있고 하위 문자열에 99개의 연속된 1이 있고 마지막으로 문자 2가 추가되면 1000회 루프에서 테스트한 후 재귀 알고리즘보다 몇 초 더 빠르고 MatchesMask()보다 20초 더 빠릅니다. 기능. 실제 여러 테스트에서는 세 가지 모두 가장 빠른 것으로 나타났지만 대부분의 경우 MatchesMask()가 더 느린 것 같고 재귀 속도도 크게 다릅니다. 제가 작성한 함수의 속도는 평균일 수 있습니다. 제가 작성한 기능은 참고용일 뿐입니다. 문제가 발생하더라도 저는 책임을 지지 않습니다.
function isABClikeAX(const abc,ax:widestring):boolean은 소스 문자열이고 ax는 하위 문자열입니다.
var
abcstart,axstart,abclength,axlength:정수;
endpartabc,endpartax,subax:widestring;
임시,abcwww,axwww:정수;
파일 시작://aaa
온도:=0;
abcstart:=1;
axstart:=1;
axwww:=1;
ABCwww:=1;
abc길이:=길이(abc);
축길이:=길이(ax);
isabclikeax:=true;
while axstart<=axlength do//소스 문자열 길이가 하위 문자열보다 크거나 같은 경우
시작 //bbb
abcstart> abclength이면
시작하다
if (ax[axlength]='*') and (axlength=axstart) then isabclikeax:=true
else isabclikeax:=false;//하위 문자열이 소스 문자열보다 긴 경우
부서지다;
끝;
ax[axstart]='?'이면
시작하다
inc(axstart);
inc(abcstart);
계속하다;
끝;
ax[axstart]='*'이면
시작하다
inc(axstart);
온도:=1;
axwww:=axstart;
abcwww:=abcstart;
계속하다;
끝;
if not((ax[axstart]='?') 또는 (ax[axstart]='*') )
시작//ccc
endpartax:=copy(ax,axstart,axlength-axstart+1)+'?*';
subax:=copy(endpartax,1,min(pos('?',endpartax),pos('*',endpartax))-1);
axstart:=axstart+min(pos('?',endpartax),pos('*',endpartax))-1;
endpartabc:=copy(abc,abcstart,abclength-abcstart+1);
if ((pos(subax,endpartabc)<>0) and (temp=1 )) 또는 ((pos(subax,endpartabc)=1) and (temp=0)) then
시작 //ddd
temp=1이면 temp:=0;
abcstart:=abcstart+(pos(subax,endpartabc)+length(subax)-1) ;
끝 //ddd
else//ddd
시작 //ddd
(temp=0) 및 (axwww>1)이면
시작하다
axstart:=axwww;
abcwww:=abcwww+1;
abcstart:=abcwww;
온도:=1;
계속하다;
끝;
isabclikeax:=false;
부서지다;
종료;//ddd
끝;//ccc
끝;//bbb
if (result) and (abcstart<=abclength) and (ax[axlength]<>'*') then isabclikeax:=false;//소스 문자열이 하위 문자열보다 긴 경우
끝;/아아아
FUNCTION IsLike(abc,ax:string):boolean://대소문자 구분 함수
시작하다
islike:=isABClikeAX(abc,ax);
끝;
FUNCTION WideCard(abc,ax:string):boolean://대소문자를 구분하지 않는 함수
시작하다
abc:=대문자(abc);
ax:=대문자(ax);
widecard:=isABClikeAX(abc,ax);
끝;
USES MATH에 주의하세요. MIN()을 사용하기 때문에 IF 문을 사용하여 MIN()을 대체할 수도 있지만 충분히 명확하지 않습니다.
올바른 통찰력을 제공하여 올바른 방향으로 수정하는 데 도움을 준 일부 네티즌에게 감사드립니다.