DELPHI's Wildcard Comparison (5th Edition)
Author: Li Junyu
email: [email protected] 2003.1.5
I thought there was no ready-made function for wildcards in DELPHI, but then I found MatchesMask(). Before I found this function, I used to make a custom function to realize this function when I was in a free state and still in the mood.
The algorithm of the program is more complicated. First add '?' at the end of the substring. *', then read the substring, look for the characters between the wildcard characters in the substring, that is, the substring in the substring, and then search in the source string to see if it contains the substring in the substring. However, it is still expensive to implement. Many twists and turns. This function implements the following functions:
1. It may be faster than the recursive algorithm and MatchesMask() in most cases;
2. Implemented correct comparison of asterisks and question marks in all cases; //This may still need time to be verified
3. Support Chinese; //Asterisks and question marks must be in English to be valid
4. Supports case-sensitive selection.
Note that there is a difference between adding asterisks at the beginning and end of the substring. This algorithm may be similar to the function implemented using the recursive algorithm on the stack, but it is actually somewhat different. It has made some improvements to the recursion. It may be faster than the recursive process in most cases. How much faster is difficult? Certainly. At least there is this estimate: when wildcard comparison is only used to find substrings, such as the source string is "1111111111" and the substring is "*11111112*", the time complexity of using the recursive algorithm is O(N*M), but I written This function will then be simplified to the time complexity of approximately calling the POS() function several times. Perhaps POS() in DELPHI can be imagined as the "Knut-Morris-Pratt (KMP) algorithm" O(N+M) below. The speed comparison with the recursive algorithm is not obvious for a small number of times. When the source string has 100 consecutive 1's and the substring has 99 consecutive 1's and finally the character 2 is added, after testing in a 1000-time loop, it is several seconds faster than the recursive algorithm and 20 seconds faster than the MatchesMask() function. seconds. My actual multiple tests show that all three are sometimes the fastest, but MatchesMask() seems to be slower most of the time, and the speed of recursion varies greatly. The function I wrote may be average in speed. It's just that the functions I wrote are for reference only. I won't be responsible for any problems if they occur.
function isABClikeAX(const abc,ax:widestring):boolean; file://abc is the source string and ax is the substring
var
abcstart,axstart,abclength,axlength:integer;
endpartabc,endpartax,subax:widestring;
temp,abcwww,axwww:integer;
begin file://aaa
temp:=0;
abcstart:=1;
axstart:=1;
axwww:=1;
abcwww:=1;
abclength:=length(abc);
axlength:=length(ax);
isabclikeax:=true;
while axstart<=axlength do//When the source string length is greater than or equal to the substring
begin//bbb
if abcstart> abclength then
begin
if (ax[axlength]='*') and (axlength=axstart) then isabclikeax:=true
else isabclikeax:=false;//When the substring is longer than the source string
break;
end;
if ax[axstart]='?' then
begin
inc(axstart);
inc(abcstart);
continue;
end;
if ax[axstart]='*' then
begin
inc(axstart);
temp:=1;
axwww:=axstart;
abcwww:=abcstart;
continue;
end;
if not((ax[axstart]='?') or (ax[axstart]='*') ) then
begin//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 )) or ((pos(subax,endpartabc)=1) and (temp=0)) then
begin//ddd
if temp=1 then temp:=0;
abcstart:=abcstart+(pos(subax,endpartabc)+length(subax)-1) ;
end//ddd
else//ddd
begin//ddd
if (temp=0) and (axwww>1) then
begin
axstart:=axwww;
abcwww:=abcwww+1;
abcstart:=abcwww;
temp:=1;
continue;
end;
isabclikeax:=false;
break;
end;//ddd
end;//ccc
end;//bbb
if (result) and (abcstart<=abclength) and (ax[axlength]<>'*') then isabclikeax:=false;//When the source string is longer than the substring
end;//aaa
FUNCTION IsLike(abc,ax:string):boolean; file://case-sensitive function
begin
islike:=isABClikeAX(abc,ax);
end;
FUNCTION WideCard(abc,ax:string):boolean; file://case-insensitive function
begin
abc:=uppercase(abc);
ax:=uppercase(ax);
widecard:=isABClikeAX(abc,ax);
end;
Pay attention to USES MATH, because MIN() is used, you can also use an IF statement to replace MIN(), but it is not clear enough.
Thank you to some netizens for giving me some correct insights, which helped me make the revision in the right direction.