Модераторы: Poseidon

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [Алгоритм] Строки: найти макс.набор слов, не имеющих общих букв 
:(
    Опции темы
KasMP
Дата 26.11.2007, 17:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 586
Регистрация: 8.8.2006

Репутация: 1
Всего: 30



П/р по теме "Строки". Нельзя использовать массивы.
Цитата(Задание)
Найти в строке самый большой набор слов, никакие два из которых не имеют общих букв.
Далее, после моих вопросов было получено несколько уточнений:
  • слово - одна буква (заглавная или строчная, латинского или русского алфавита), а также их любая комбинация;
  • слово может содержать цифры (например: "3" - не слово; "п67ы" - слово);
  • цифры повторятся могут;
  • пробел и знаки препинания (а именно: точка, запятая, двоеточие, точка с запятой, вопросительный и восклицательный знаки) - разделители (например: "стройная, красивая девушка" - 3 слова; "dgh3dg?4 ghd!fc" - тоже 3 слова ("dgh3dg", "ghd" и "fc"));
  • найти нужно именно максимальное кол-во слов (а не, например, слова, содержащие максимальное кол-во неповторяющихся букв).
Пока мой мозг додумался только до того, что самое "выгодное" слово - слово, состоящее из одной буквы ("поедает" минимальное кол-во букв и приносит максимальное кол-во слов, которые можно составить из одной буквы). Чем меньше букв в слове, тем оно "лучше".
Ну и еще до того, что, наверно, нужно организовать три строки:
а) исходная - к ней не прикасаемся (или заменяем/удаляем лишь то, что точно не понадобится и только мешает (пока не знаю, что это может быть);
б) рабочая - в которой перебираем варианты, составляем разные комбинации;
в) промежуточно-результативная - в которой сохраняем наилучший вариант, полученный на данный момент.

Причем пока я вижу промежуточно-результативную строку примерно (слово совсем не для программиста, а для какого-то гуманитария-филолога-трепача, ну да ладно...) так: сохраняем кол-во слов, сохраняем уже задействованные буквы, сохраняем использованные слова.
Т.е. лучше вообще разделить все это (промежуточный результат) на 3 разных переменных:
а) переменная целого типа - кол-во слов;
б) переменная-строка - записываем уже задействованные буквы;
в) переменная-строка - записываем через пробел слова (чтобы потом в случае чего вывести).

Примерно тот же подход можно применить и к рабочей "строке" (только без переменной, коллекционирующей, слова - она ей ни к чему; задача рабочей строки - просто перебрать и посчитать кол-во слов, а не выдать набор слов):
а) переменная целого типа - кол-во слов;
б) переменная-строка - записываем уже задействованные буквы.


Короче не знаю, путано все, сложно и непонятно... smile 
Помогите, пожалуйста! Спасибо за то, что обратили внимание на мою полуламерскую, очень смутную тему.
PM MAIL   Вверх
JackYF
Дата 26.11.2007, 18:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

Репутация: 2
Всего: 162



Цитата(KasMP @  26.11.2007,  17:53 Найти цитируемый пост)
Нельзя использовать массивы.

Круто. А что можно? строка - не массив?  smile 

В общем, идея дубового решения такова (очень похожа на идею решения задачи на графах, правда, какой, не помню smile):

1. Выделить все слова из строки.
2. Из каждого слова сформировать набор, пока состоящий из этого слова.
3. Затем, для каждой группы и для каждого другого слова сравнить его набор букв с набором букв слов из группы, если не совпали, добавить в группу.
После этого этапа мы будем иметь группы из одного слова и группы из двух. Группы из одного слова нам уже не нужны, забиваем на них.
4. Повторяем процедуру №3, вычёркиваем все группы, состоящие уже из двух слова, оставляем только трёхсловные группы.
4+. И так далее, пока нечего будет добавлять к группам.
5. Пройтись по группам, подсчитать количество слов в группах.

Как это дело организовать "без массивов", я не очень себе представляю. Массив - одна из базовых структур языка программирования, без них как без ног...


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
Akina (Online)
Дата 26.11.2007, 18:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 17
Всего: 454



Для начала поменяй все символы-разделители на, скажем, пробелы.
Сперва посчитай количество слов (нельзя массивы - можно байтовую маску), создай строку с количеством байтов = количеству слов.

И понеслась... берем слово 1. Прикладываем слово 2, проверяем на соответствие условию. Да? к полученной группе прикладываем слово 3... нет? откидываем вариант 2, берем вариант 1-3... пробуем приложить слово 4.... и так перебираем все возможнвые варианты. На каждом шаге смотрим количество слов в группе, и запоминаем, если она больше предыдущей запомненной...


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
KasMP
Дата 26.11.2007, 23:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 586
Регистрация: 8.8.2006

Репутация: 1
Всего: 30



Цитата(JackYF @  26.11.2007,  18:33 Найти цитируемый пост)
Круто. А что можно? строка - не массив?
Я не спорю, строка - разновидность массива smile ... Но дословно было сказано именно так smile .
Цитата(JackYF @  26.11.2007,  18:33 Найти цитируемый пост)
В общем, идея дубового решения такова (очень похожа на идею решения задачи на графах, правда, какой, не помню smile):
Спасибо за дубовый алгоритм (в нем тоже есть своя прелесть smile ). Но у нас упор делается именно на рациональность алгоритма, его низкую сложность, красоту построения, т.п..
Цитата(JackYF @  26.11.2007,  18:33 Найти цитируемый пост)
Как это дело организовать "без массивов", я не очень себе представляю. Массив - одна из базовых структур языка программирования, без них как без ног... 
А вот я попробую подумать smile и представить smile  . Это же интересно... smile 
_____________________________________________________________________
Цитата(Akina @  26.11.2007,  18:39 Найти цитируемый пост)
Для начала поменяй все символы-разделители на, скажем, пробелы.
У меня была такая мысль. Но зачем?
Имхо программа не станет проще от того, что вместо сравнения символа с несколькими заданными символами-разделителями
 будет производиться сначала поиск разделителей (т.е. по сути опять то же сравнение, о котором говорилось только что), а затем замена, а посл снова поиск.
Хотя smile ... Ведь при поиске слов мы будем обращаться к одному и тому же символу далеко не один раз (рассматриваем разные комбинации). Т.е. с этой зрения рациональнее все же заменить: вместо многократных сравнений с несколькими символами мы получим многократные сравнения с одним символом -> сложность уменьшается в разы. Кажется, я поняла!
Цитата(Akina @  26.11.2007,  18:39 Найти цитируемый пост)
байтовую маску
Я пыталась понять, что это здесь и здесь. Видимо, не там искала?
PM MAIL   Вверх
Akina (Online)
Дата 27.11.2007, 10:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 17
Всего: 454



Цитата(KasMP @  27.11.2007,  00:54 Найти цитируемый пост)
Я пыталась понять, что это 

В данном случае это строка байтов (с ними проще работать, чем с битами, а по памяти нас не ограничивали), которые будут показывать, какой набор слов мы проверяем в текущий момент... скажем плюс - проверяем, минус - нет... значение байта произвольно.


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
KasMP
Дата 27.11.2007, 15:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 586
Регистрация: 8.8.2006

Репутация: 1
Всего: 30



А если не доходит, как реализовать это на паскале, то лучше создать новую тему (чтобы был порядок) или можно продолжить здесь (чтобы не забивать форум)? 
Цитата(Akina @  26.11.2007,  18:39 Найти цитируемый пост)
проверяем на соответствие условию
В данном случае подразумевается, что мы берем каждую букву первого слова и сравниваем ее с каждой буквой второго (т.е. занимаемся простым перебором)? Или что?
(потом каждую буквы первых двух с каждой буквой третьего и т.д.?)
Цитата(Akina @  27.11.2007,  10:06 Найти цитируемый пост)
по памяти нас не ограничивали
Как сказать... Чем меньше памяти - тем лучше (даже в нашем случае). Думаю, это будет оценено и принято во внимание преподавателем (и я тоже хочу сделать максимально хорошо).

Вот, например, строчка:
Цитата
dr6v!пу?56vf hf;!d 5?gdке
1. заменяем разделители на пробелы (несколько идущих подряд разделителей заменяем на один пробел (другими словами, если ((s[i-1]=разделитель_кром) и (s[i]=разделитель)), то s[i-1] уже заменен на пробел, а s[i] просто удаляем)).
Результат: "dr6v пу 56vf hf d 5 gdке".
2. вычеркиваем "не слова" (другими словами, одну или несколько цифр, окруженных пробелами).
Результат: "dr6v пу 56vf hf d gdке".
3. считаем кол-во слов (на это ума много не надо).
Результат: "6" (обозначим как t).
4. создаем строку с кол-вом байтов, равном кол-ву слов (другими словами, ... (что мы делаем?!?!).
Результат: пустая строка с кол-вом байтов, равном t.
5. ух, чего-то там делаем... (не дошло).
6. еще чего-то делаем... (группируем, прикладываем, не знаю, не дошло...).
7. какие-то "да"/"нет"... (примерно понятно, но нет конкретики, т.к. пробелы в понимании предыдущих шагов).
8. не забываем при каждой новой комбинации обновлять кол-во слов в группе, если оно больше предыдущего значения.
9. ну а теперь любой баран сможет взять нужные переменные и вывести их как результат.

Кстати, может быть, компу удобнее заменять разделители не на пробелы, а на что-то, что расположено в используемых таблица ближе (символ с кодом N достигается немного быстрее, чем символ с кодом N+K)? Нет?


 smile  smile  smile  smile  smile 
 smile  smile  smile  smile  smile 

Это сообщение отредактировал(а) KasMP - 27.11.2007, 15:11
PM MAIL   Вверх
GIK
Дата 27.11.2007, 16:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Добрый человек
**


Профиль
Группа: Участник
Сообщений: 985
Регистрация: 3.6.2005
Где: я только не небыв ал

Репутация: 4
Всего: 14



Яб сделал так:
1) Можно конечно заменить все знаки припинания на пробелы, но можно и в условии просто проверять (причем побитово) на всме имеющиеся знаки препинания. Короче, в массиве сохраняем "якоря" (так я называю индексы эллементов некоторой сушьности)
2) Подсчитали кол-во пропусков, пропускаем через цикл эти индексы, например так:
 
Код

for(int i=0; i<12; i++) //Допустим 12 пробелов
 { 
   int len= mas[i+1] - mas[i]; //Нужна вычислить длину слова
   
    for(int d=1; d<=len; d++) //Берем каждую букву с самого начала 
     for(int ch=d+1; ch<=len; ch++) //возвращатся нет смысла, так что с d и дальше
    { 
        if(str[mas[i]+d]==str[mas[i]+ch])
         not=true; //Нашли, обломались, ну фиг с ним :)
        //str[mas[i]+d]; //читается как, индекс начала слова+последующие буквы
    }
  if(!not)
      //Забиваем массив слов которые не имеют одинаковых букв
  
}
3) Все вроде...

Это сообщение отредактировал(а) GIK - 27.11.2007, 16:08


--------------------
Математика=>пиво=> програмирование, три вещи последовательны и совместимы !!!
Программирование - это не деятельнось! Программирование - это состояние души!
Бог - самый крутой программист.
PM MAIL ICQ   Вверх
KasMP
Дата 27.11.2007, 18:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 586
Регистрация: 8.8.2006

Репутация: 1
Всего: 30



GIK, а где у тебя сохраняется промежуточный (наилучший на данный момент) результат? Имхо если мы нашли совпадение и обломались, то не фиг, а надо сначала сравнить этот "фиг" с наилучшим на данный момент результатом.
К слову, массивы использовать нельзя.

(кругом одни сишники smile , только у нас паскаль :(( ;
вот никак не могу понять: нахрена на наш факультет прутся те, кто не знает паскаль, ни разу не слышал о массивах, не восторгается красотой программирования, не чувствует его совершенства, а делают что-то только потому, что кто-то  там сказал и спросит это позже..; вот зачем они занимают чьи-то места? если не знали куда пойти, если не тянуло ни к чему, то шли бы в сельхоз-академию и были бы агрономами...)

PM MAIL   Вверх
Akina (Online)
Дата 27.11.2007, 18:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 17
Всего: 454



Попробую пояснить мысль подбора вариантов. Допустим, у нас вот те самые 6 слов "dr6v пу 56vf hf d gdке". Я буду оперировать битовой маской, а байтовую предложил для того, чтобы в Паскале тебе не заморачиваться на биты и лишние вычисления.

Начинаем, само собой, с 000000. Оно смысла не имеет, значит сразу с 000001.
Это "gdке". Запускаем в тест повтора символов - на выходе нам говорят что повтора нет. Запоминаем текущее наилучшее (1 слово) и соотв. маску (000001).
Далее прибавляем к маске единичку - получаем 000010. Это "d". Запускаем в тест повтора символов - на выходе нам говорят что повтора нет. Сравниваем длину - 1 слово, у нас такой вариант есть. Пропускаем.
Далее прибавляем к маске единичку - получаем 000011. Это "d gdке". Запускаем в тест повтора символов, удалив разделители, т.е. "dgdке" - на выходе нам говорят что повтор есть. Пропускаем.
Далее 000100 = "hf". Нет. 1. Пропускаем.
Далее 000101 = "hfgdке". Нет. 2. Запоминаем.
Далее 000110 = "hfd". Нет. 2. Пропускаем.
Далее 000101 = "hfdgdке". Да. Пропускаем.

И так далее.

В данном случае пример не очень удачен - произойдет полный перебор вариантов. Но на самом деле в реальной работе будут пропуски, например:

Если маска 010100 дает дублирование символов, то мы переходим не к 010101, а сразу к 011000, потому что проверка 010101..010111 бессмысленна. Т.е. на каждом шагу мы прибавляем к маске 1, если в текущей группе не было дублирования символов, и единичку в последний ненулевой бит текущей маски (в приведенном примере это третий от хвоста бит), если оно было.



--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
GIK
Дата 28.11.2007, 12:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Добрый человек
**


Профиль
Группа: Участник
Сообщений: 985
Регистрация: 3.6.2005
Где: я только не небыв ал

Репутация: 4
Всего: 14



Цитата

а надо сначала сравнить этот "фиг" с наилучшим на данный момент результатом.
К слову, массивы использовать нельзя.

Я наверно задачу не правильно понял smile 
Надо было найти слова не имеющие общих букв, а я отсекал слова имеющие одинаковые буквы в этом же слове, лоханулся короче smile 
Вобщем строки использовать нельзя, так?



--------------------
Математика=>пиво=> програмирование, три вещи последовательны и совместимы !!!
Программирование - это не деятельнось! Программирование - это состояние души!
Бог - самый крутой программист.
PM MAIL ICQ   Вверх
SaDFromSpb
Дата 28.11.2007, 17:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 263
Регистрация: 5.4.2006
Где: Санкт-Петербург

Репутация: нет
Всего: 3



Цитата(Akina @  27.11.2007,  18:57 Найти цитируемый пост)
В данном случае пример не очень удачен - произойдет полный перебор вариантов.

Вроде как, это задача на NP-полноту, то есть самое оптимальное решение может быть достигнуто только полным перебором. (Отбрасывание заведомо лишних комбинаций здесь не в счет). Чтобы утверждать наверняка, нужно это четко доказать. Как это делается, я не знаю. 



--------------------
"За исключением части, касающейся потоков, библиотека Loki написана на стандартном языке С++. Увы, это означает, что многие современные компиляторы не смогут работать с ней в полном объеме." (А. Александреску. Modern C++ design. 2001)
PM   Вверх
Akina (Online)
Дата 28.11.2007, 18:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 17
Всего: 454



Цитата(SaDFromSpb @  28.11.2007,  18:59 Найти цитируемый пост)
Вроде как, это задача на NP-полноту, то есть самое оптимальное решение может быть достигнуто только полным перебором. 

Верно. Впрочем, при правильном построении программы (в данном случае это может быть например перестроение слов с сортировкой их символов + сортировка слов по длине) количество отбрасываемых вариантов может гарантированно составлять более половины возможных.

Цитата(SaDFromSpb @  28.11.2007,  18:59 Найти цитируемый пост)
Чтобы утверждать наверняка, нужно это четко доказать.

Достаточно того, что вероятность наличия какого-либо символа в каком-либо слове не может быть рассчитана на основании знания части или всех остальных слов. Т.е. каждое из слов полностью независимо. Впрочем, можно доказать, что ПОЛНОГО перебора в общем случае нет - количество слов в группе заведомо не больше количества символов в алфавите, но на суть это не влияет.


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
KasMP
Дата 2.12.2007, 15:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 586
Регистрация: 8.8.2006

Репутация: 1
Всего: 30



Цитата(Akina @  27.11.2007,  18:57 Найти цитируемый пост)
Попробую пояснить мысль подбора вариантов.
Спасибо большое, теперь ясно!
Правда есть недочет: формулировка "никакие 2 из которы не имеют общих букв" подразумевает, что внутри одного слова буквы могут повторяться (т.е. склеивать слова в одну строку и только потом сравнивать нельзя).
Цитата(GIK @  28.11.2007,  12:46 Найти цитируемый пост)
Я наверно задачу не правильно понял
 Возможно.
Цитата(GIK @  28.11.2007,  12:46 Найти цитируемый пост)
Вобщем строки использовать нельзя, так?
 Строки можно и нужно, просто необходимо использовать - к/р по теме "Строки".

А то, что написано в посте Akina от 28.11.2007, 18:41 приведу тогда, когда опять преподаватель начнет: "но это же просто перебор... слишком много раз бегаем по строке..." (при этом ничего более оптимального не предлагает!!)
PM MAIL   Вверх
KasMP
Дата 9.12.2007, 10:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 586
Регистрация: 8.8.2006

Репутация: 1
Всего: 30



Пожалуйста, не бросайте на произвол судьбы!!
PM MAIL   Вверх
skyboy
Дата 15.12.2007, 14:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

Репутация: 5
Всего: 260



все пытаюсь привести постановку задачи к задаче на графах.
пока "дошел" до уровня матрицы смежности.
пускай матрица определяется так: каждая ячейка {i,j} представляет собой флаг(1 или 0) - является ли слово i имеющим общие со словом j буквы(1 - если имеются, 0 - еслши не имеются). все ячейки с одинаковым номером столбца и строки - имеют значение 0(для упрощения считаем, что слово с самим собой общих букв не имеет). Тогда у нас будет матрица из 0 и 1 размерностью NxN. Удаление слова из списка - удаление строки и столбца с одинаковым номером. теперь надо удалить минимальное количество строк, чтоб оставшаяся матрица состояла из одних нулей.
PM MAIL   Вверх
Страницы: (3) Все [1] 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Центр помощи"

ВНИМАНИЕ! Прежде чем создавать темы, или писать сообщения в данный раздел, ознакомьтесь, пожалуйста, с Правилами форума и конкретно этого раздела.
Несоблюдение правил может повлечь за собой самые строгие меры от закрытия/удаления темы до бана пользователя!


  • Название темы должно отражать её суть! (Не следует добавлять туда слова "помогите", "срочно" и т.п.)
  • При создании темы, первым делом в квадратных скобках укажите область, из которой исходит вопрос (язык, дисциплина, диплом). Пример: [C++].
  • В названии темы не нужно указывать происхождение задачи (например "школьная задача", "задача из учебника" и т.п.), не нужно указывать ее сложность ("простая задача", "легкий вопрос" и т.п.). Все это можно писать в тексте самой задачи.
  • Если Вы ошиблись при вводе названия темы, отправьте письмо любому из модераторов раздела (через личные сообщения или report).
  • Для подсветки кода пользуйтесь тегами [code][/code] (выделяйте код и нажимаете на кнопку "Код"). Не забывайте выбирать при этом соответствующий язык.
  • Помните: один топик - один вопрос!
  • В данном разделе запрещено поднимать темы, т.е. при отсутствии ответов на Ваш вопрос добавлять новые ответы к теме, тем самым поднимая тему на верх списка.
  • Если вы хотите, чтобы вашу проблему решили при помощи определенного алгоритма, то не забудьте описать его!
  • Если вопрос решён, то воспользуйтесь ссылкой "Пометить как решённый", которая находится под кнопками создания темы или специальным флажком при ответе.

Более подробно с правилами данного раздела Вы можете ознакомится в этой теме.

Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Poseidon, Rodman

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Центр помощи | Следующая тема »


 




[ Время генерации скрипта: 0.1036 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.