Вопросец возник...
- From
- Evgeniy Jirnov (2:5030/1230.13)
- To
- Oleg Khovayko ()
- Date
- 2003-01-27T12:31:18Z
- Area
- RU.ALGORITHMS
Мир твоему дому, Oleg.
25 Янв 03 04:48, Oleg Khovayko -> Evgeniy Jirnov:
>> Что-то я не соображу: бинарный поиск imho применить нельзя.
OK> Нельзя. точно.
А жаль...
>> Не перебирать же 3000 строк на совпадение с маской по возрастанию?
OK> А придется! :(
OK> На самом деле, существуют методы, упрощающие твою задачу.
OK> По списку масок надо строить конечный автомат, который и будет
OK> тебе для каждой строки возвращать список масок, к которым
OK> подходит данная строка.
На самом деле можно мою задачу можно упростить, но тогда я получу уменьшение скорости непонятно на сколько. А суть такова: в данный момент я перебираю 3000 строк и для каждой строки прогоняю 500 масок. Если перебирать 500 масок и для каждой перебирать 3000 строк, тогда можно сильно упростить задачу: во-первых, у меня довольно мало масок, где первый символ - "*", во-вторых маски отсортированы по возрастанию... Но если сделать так, то я получу ограничение на 16k строк...
>> Причем масок
>> около 500. Получается мне надо перебрать 3000*500=1500000
>> комбинаций? :(
OK> Ага.
OK> Чем реально могу пособить - в свое время я написал эффективную
OK> процедуру сравнения имени файла с маской, которая в худшем случае
OK> производит (A+1)*L операций сравнения, где А - число звездочек в
OK> маске, а L - длина строки-кандидата.
OK> Хочу заметить, что это существенно лучше того, что сейчас применяется
OK> в UNIX-ах. Ибо UNIX shell можно в легкую положить такой
OK> последовательностью команд:
OK> touch aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
OK> ls *a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*b
Гхм... У меня процедура сравнения строки с маской производит довольно мало сравнений и не валится на такой строчке и маске. Вот ее исходный текст:
{────────────────────────────────────────────────────────────────────────────}
type
TCheckWildcardStack = packed record
Src,
Mask: Byte;
end;
function CheckMask(const Src, Mask: String): Boolean;
var
Stack: array[1..128] of TCheckWildcardStack;
StackPointer,
SrcPosition, MaskPosition,
SrcLength, MaskLength: Byte;
begin
CheckMask:=False;
if (Mask = '') and (Src <> '') then Exit;
MaskLength:=Length(Mask);
SrcLength:=Length(Src);
if Mask[MaskLength] <> '*' then
while (MaskLength > 1) and (SrcLength > 1) do
begin
if (Mask[MaskLength] = '*') or (Mask[MaskLength] = '?') then Break;
if Mask[MaskLength] <> Src[SrcLength] then Exit;
Dec(MaskLength);
Dec(SrcLength);
end;
if Mask[MaskLength] = '*' then
while (Mask[MaskLength - 1] = '*') and (MaskLength > 1) do Dec(MaskLength);
StackPointer:=0;
SrcPosition:=1;
MaskPosition:=1;
while (SrcPosition <= SrcLength) and (MaskPosition <= MaskLength) do
begin
case Mask[MaskPosition] of
'?':
begin
Inc(SrcPosition);
Inc(MaskPosition);
end;
'*':
begin
if (MaskPosition = 1) or (Mask[MaskPosition - 1] <> '*') then Inc(StackPointer);
Stack[StackPointer].Mask:=MaskPosition;
Inc(MaskPosition);
if MaskPosition <= MaskLength then
if (Mask[MaskPosition] <> '?') and (Mask[MaskPosition] <> '*') then
while (SrcPosition <= Length(Src)) and (Src[SrcPosition] <> Mask[MaskPosition]) do Inc(SrcPosition);
Stack[StackPointer].Src:=SrcPosition + 1;
end;
else
if Src[SrcPosition] = Mask[MaskPosition] then
begin
Inc(SrcPosition);
Inc(MaskPosition);
end else
begin
if StackPointer = 0 then Exit;
SrcPosition:=Stack[StackPointer].Src;
MaskPosition:=Stack[StackPointer].Mask;
Dec(StackPointer)
end;
end;
while not ((SrcPosition <= SrcLength) xor (MaskPosition > MaskLength)) do
begin
if (MaskPosition >= MaskLength) and (Mask[MaskLength] = '*') then Break;
if StackPointer = 0 then Exit;
SrcPosition:=Stack[StackPointer].Src;
MaskPosition:=Stack[StackPointer].Mask;
Dec(StackPointer)
end;
end;
CheckMask:=True;
end;
{────────────────────────────────────────────────────────────────────────────}
Не знаю правда чья она, но автору огромнейшее спасибо...
С уважением _Evgeniy_
... 83 AB E3 AF A0 EF 20 E2 E0 A0 E2 A0 20 A2 E0 A5 AC A5 AD A8 21
--- np: Enigma - Track 6
* Origin: А вы и ухом не моргнули (2:5030/1230.13)