Re: Вопросец возник...
- From
- Oleg Khovayko ()
- To
- Evgeniy Jirnov ()
- Date
- 2003-01-28T11:36:11Z
- Area
- RU.ALGORITHMS
From: Oleg Khovayko <olegh@hotpop.com>
Evgeniy Jirnov wrote:
> каждой перебирать 3000 строк, тогда можно сильно упростить задачу: во-первых, у
> меня довольно мало масок, где первый символ - "*"
Еще, наверное, у Вас мало масок, где последний символ - "*".
При желании можно создать вторую пару массивов строк и масок,
где строки записаны задом наперед. И опять их отсортировать.
Получите два "префильтра", которые эффективно отбросят
основную массу случаев.
Ну а остальные - прямым перебором, MxN.
Еще один, 3-й, префильтр можно ввести, исходя из след. предположения:
Если в маске присутствует N символов X, и M символов Y, и тп,
то в строке, подходящей под маску, символов X должно быть не
менее, чем N, символов Y должно быть не менее, чем M, и тп.
Но на самом деле, для эффективной реализации последнего префильтра
надо 256 байт на каждую маску и столько же - на каждого кандидата.
Поэтому целесообразность третьего фильтра весьма сомнительна...
> Но если сделать так, то я получу ограничение на
> 16k строк...
Что-то я не соображу, откуда такое странное ограничение взялось.
Хотя Вам с горы виднее... ;)
> OK> touch aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
> OK> ls *a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*b
>
> Гхм... У меня процедура сравнения строки с маской производит довольно мало
> сравнений
Это _Вы_ так считаете, что мало. Попробуйте в основной while вставить
счетчик, и посмотрите, сколько циклов она накрутит.
> и не валится на такой строчке и маске.
А не валится потому, что в Вашей процедуре просто есть
дополнительная проверка на совпадение символов в конце
строки/маски. Если в конце маски будет присутствовать
звездочка, эта доп. проверка не сработает, и алгоритм
свалится в факториал.
Попробуйте ей такой вот тест подсунуть:
Str: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Mask: *a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*b*
Извините, Паскаля у меня нету, чтобы самому проверить.
А перепирать грамадную процедуру на C лениво.
То есть приведенный Вами алгоритм - из той же серии,
что и UNIX-ная убогость. Отличается только "заплатой",
которая перед тем, как в факториал свалиться,
в конец строки смотрит.
> Вот ее исходный текст:
Какая-то она большая и запутаная.
И вроде как даже без глюков, за исключением:
- пустая строка в ней подходит под любую маску.
- для маски = "*" и пустой входной строки идет попытка
обращения за левую границу массива маски по
нулевому индексу.
Ниже - моя процедура fmask1 на C, которая свободна от
указаных выше багов.
/* fmask dynamic procedure
# Wrote by Oleg H. http://olegh.spedia.net
# Oct, 11, 2002
# Version 2
# Distributes according GPL
*
* Limits:
* 1. String lenght < 256
* 2. Stars <= 32
*/
#include <stdio.h>
#include <stdlib.h>
#define LEN 256
static unsigned long dp_stars[LEN];
//---------------------------------------------------------
static int fmask1(const char *mask, const char *str, unsigned long deep) {
unsigned long *dp_el;
if(deep == 0) return 0; // Owerflow 32 stars
for( ; ; str++) {
switch(*mask++) {
case '*' : dp_el = dp_stars + (unsigned char)str;
if(!(*dp_el & deep) && fmask1(mask, str, deep << 1))
return 1;
*dp_el |= deep;
mask--;
case '?' : if(*str == 0) return 0;
continue;
case 0 : return *str == 0;
default : if(mask[-1] != *str) return 0;
continue;
} // switch
} // for
} // Function fmask1
//---------------------------------------------------------
void main() {
char mask[LEN], str[LEN];
const char *rc;
for( ; ; ) {
printf("\nEnter mask and str: ");
scanf("%s%s", mask, str);
memset(dp_stars, 0, LEN * sizeof(unsigned long));
rc = fmask1(mask, str, 1)? "OK" : "BAD";
printf("\nmask:[%s] str:[%s]; Result: %s\n", mask, str,
rc);
}
}
--- ifmail v.2.15dev5
* Origin: Demos online service (2:5020/400)