roboforum.ru

Технический форум по робототехнике.

Простая задачка по программированию

Все здесь

Простая задачка по программированию

Сообщение Montoya » 24 мар 2009, 18:09

Готовился я тут к олимпиаде по программированию, и препод дала мне задачу, которая была в 2005 году на городской олимпиаде для НЕпрофессионалов. Сама задача:
Даны 2 фразы, программа должна найти максимальную последовательность символов (не обязательно стоящих подряд), входящую в обе фразы, пример

ПРИШЛА ВЕСНА
РАСТАЯЛ СНЕГ

программа должна вывести РАСН

Я долго долбался над ней, и так ее и не решил, кстати и препод, и ее сын,профессиональный программист, на 100% решить ее не смогли :) Может кто-нибудь попробует ее решить?

ЗЫ сын препода написал эту задачу,используя сложную рекурсию, которая смогла вывести РАСН, но если ввести в его программу "наступила весна" и "расцвели подснежники" программа выводит "НЕ" ....
Аватара пользователя
Montoya
 
Сообщения: 168
Зарегистрирован: 14 авг 2007, 15:16
Откуда: Ростов-на-Дону
прог. языки: C/C++
ФИО: Герасимов Иван

Re: Простая задачка по программированию

Сообщение Myp » 24 мар 2009, 18:22

эммм
а тупо перебором?
берём 1 букву 1 строки и ищем её во второй строке
если нашли запоминаем позицию найденной буквы и запоминаем последовательность
берём вторую букву первой строки и ищем в второй строке начиная с запомненной позиции
нету, хорошо, берём третью букву 1 строки и ищем начиная с запомненной позиции во второй строке
нету, хорошо, берём четвёртую букву 1 строки и ищем начиная с запомненной позиции во второй строке
находим и запоминаем результат и позицию
берём 5 букву и ищем начиная с запомненной позиции
таким макаром прогоняем все комбинации возможные

их конечно будет дофига комбинаций особенно если предложение длинное
но в итоге получим список возможных вариантов последовательностей в строке и выберем наилучший
<telepathmode>На вопросы отвечает Бригадир Телепатов!</telepathmode>
Всё уже придумано до нас!
Аватара пользователя
Myp
скрытый хозяин вселенной :)
 
Сообщения: 18018
Зарегистрирован: 18 сен 2006, 12:26
Откуда: Тверь по прозвищу Дверь
прог. языки: псевдокод =) сила в алгоритме!
ФИО: глубокоуважаемый Фёдор Анатольевич

Re: Простая задачка по программированию

Сообщение Montoya » 24 мар 2009, 18:40

Ну у меня похожие мысли,я просто вытащил все буквы, которые есть в обоих фразах и запомнил их координаты... надо подумать над перебором
Аватара пользователя
Montoya
 
Сообщения: 168
Зарегистрирован: 14 авг 2007, 15:16
Откуда: Ростов-на-Дону
прог. языки: C/C++
ФИО: Герасимов Иван

Re: Простая задачка по программированию

Сообщение Myp » 24 мар 2009, 18:44

кстати да
для быстроты надо удалить все буквы которые встречаются один раз
<telepathmode>На вопросы отвечает Бригадир Телепатов!</telepathmode>
Всё уже придумано до нас!
Аватара пользователя
Myp
скрытый хозяин вселенной :)
 
Сообщения: 18018
Зарегистрирован: 18 сен 2006, 12:26
Откуда: Тверь по прозвищу Дверь
прог. языки: псевдокод =) сила в алгоритме!
ФИО: глубокоуважаемый Фёдор Анатольевич

Re: Простая задачка по программированию

Сообщение Denis_Wozniak » 24 мар 2009, 19:38

Программа готова!
"наступила весна" и "расцвели подснежники" программа выводит "НЕ"

2 варианта ответа!: "АСВЕСН" и "АСИ ЕН"

Если нужен код, тогда в личку стучитесь. 8)

Добавлено спустя 3 минуты 16 секунд:
Да, бог с ней.

Код: Выделить всёРазвернуть
Dim T1 As String, T2 As String, MaxT As String, Len1 As Long, Len2 As Long

Private Sub Main()
T1 = "наступила весна"
T2 = "расцвели подснежники"
Len1 = Len(T1)
Len2 = Len(T2)

Perebor "", 0, 0
Print MaxT
End Sub

Sub Perebor(ByVal Combination As String, N1 As Long, N2 As Long)
Dim I As Long, Nn As Long, Ss As String

For I = N1 + 1 To Len1
    Ss = Mid(T1, I, 1)
    Nn = FindN(N2 + 1, Ss)
    If Nn > 0 Then
        Perebor Combination + Ss, I, Nn
    Else
        If Len(Combination) > Len(MaxT) Then MaxT = Combination
    End If
Next I
End Sub

Function FindN(ByVal n As Long, Buka As String)
FindN = InStr(n, T2, Buka)
End Function


На бейсике быстрее просто :pardon:

Добавлено спустя 4 минуты 40 секунд:
Задача десяти минут!
Аватара пользователя
Denis_Wozniak
 
Сообщения: 175
Зарегистрирован: 31 дек 2008, 22:47
Откуда: Подмосковье, Ногинск
прог. языки: С, С++, Ну и начинал я в Visual Basic.

Re: Простая задачка по программированию

Сообщение Montoya » 24 мар 2009, 19:41

Хы, пасиб.... еще бы ща понять что оно делает и попробывать это перекинуть на си или хотябы на паскаль.... Лан, вечером попробую разобраться, а то ща бошка всякой социологией и экономикой забита :bad: ....
ЗЫ скорее всего организаторы этой олимпиады взяли эту задачу из какой-нибудь книги по васику :)
Аватара пользователя
Montoya
 
Сообщения: 168
Зарегистрирован: 14 авг 2007, 15:16
Откуда: Ростов-на-Дону
прог. языки: C/C++
ФИО: Герасимов Иван

Re: Простая задачка по программированию

Сообщение Denis_Wozniak » 24 мар 2009, 20:04

социологией и экономикой
:bad:
Я и паскаль знаю(тож нада было для олимпиады выучить)
Ща перепишем.

Добавлено спустя 20 минут 41 секунду:
Нее.
Вломину переписывать.

Вот расшифровочка

Len - Length
Mid - Copy
Instr - Pos

Вот собстно и всё.
Аватара пользователя
Denis_Wozniak
 
Сообщения: 175
Зарегистрирован: 31 дек 2008, 22:47
Откуда: Подмосковье, Ногинск
прог. языки: С, С++, Ну и начинал я в Visual Basic.

Re: Простая задачка по программированию

Сообщение =DeaD= » 24 мар 2009, 21:16

2Denis: Решение конечно похоже на действующее (в ломы разбирать бейсиковый код с глобальными переменными :)), но не оптимальное.

Оптимальное решение такой задачи - классическое динамическое программирование.

Кто на олимпиады ходит - должен знать этот метод :wink:
Проект [[Open Robotics]] - Универсальные модули для построения роботов
Аватара пользователя
=DeaD=
 
Сообщения: 24218
Зарегистрирован: 06 окт 2004, 18:01
Откуда: Ебург
прог. языки: C++ / PHP / 1C
ФИО: Антон Ботов

Re: Простая задачка по программированию

Сообщение Montoya » 24 мар 2009, 21:21

Хм....ща будем гуглить :oops:
Аватара пользователя
Montoya
 
Сообщения: 168
Зарегистрирован: 14 авг 2007, 15:16
Откуда: Ростов-на-Дону
прог. языки: C/C++
ФИО: Герасимов Иван

Re: Простая задачка по программированию

Сообщение =DeaD= » 24 мар 2009, 21:25

Ага, почитай, очень мощный метод, очень часто в задачах применяется, и самое главное - нереально быстрый :)

Если что задавай вопросы, но описывать подходы с нуля - ломает :) да и примеров надо кучу приводить...

Добавлено спустя 54 секунды:
PS 2Denis: Если на олимпиадах участвуешь по информатике - тоже обязательно метод почитай, в каждой второй-третьей задаче почти встречается :)
Проект [[Open Robotics]] - Универсальные модули для построения роботов
Аватара пользователя
=DeaD=
 
Сообщения: 24218
Зарегистрирован: 06 окт 2004, 18:01
Откуда: Ебург
прог. языки: C++ / PHP / 1C
ФИО: Антон Ботов

Re: Простая задачка по программированию

Сообщение Denis_Wozniak » 24 мар 2009, 22:28

Хм...
ДинамоПрогр-ие?
Вы предлагате разбросать строки в массивы? :)
В Паскале со строкой, как массивом работать можно.
Аватара пользователя
Denis_Wozniak
 
Сообщения: 175
Зарегистрирован: 31 дек 2008, 22:47
Откуда: Подмосковье, Ногинск
прог. языки: С, С++, Ну и начинал я в Visual Basic.

Re: Простая задачка по программированию

Сообщение Montoya » 24 мар 2009, 22:36

Та суть метода не в этом, там , в часности для нахождения НОП (наибольшая общая подпоследовательность), заполняется таблица значениями функции (которая определяет max длину), которые были вычислены раньше.Или я не прав?

Добавлено спустя 1 минуту 54 секунды:
Будем решать эту задачу методом динамического программирования. Для этого опишем подзадачи, на которые мы будем разбивать нашу задачу. Мы напишем функцию LCS(p, q), которая находит длину НОП для двух начальных участков a1, …, ap и b1, …, bq наших последовательностей. Пусть для всех пар q и p (p < n, q < m), мы задачу решать уже научились. Попробуем вычислить LCS(n, m). Рассмотрим два случая:


1) an= bm. Тогда LCS(n, m)=LCS(n-1, m-1)+1.


2) an≠ bm. Тогда LCS(n, m)=max(LCS(n, m-1), LCS(n-1, m)).


Пользуясь этими формулами, мы можем заполнить таблицу значений LCS(p, q) для всех p и q последовательно: сначала заполняем первую строчку слева направо, затем вторую и т.д. Последнее число в последней строке и будет ответом на поставленную задачу.


Данный алгоритм требует порядка O(nm) операций.
Аватара пользователя
Montoya
 
Сообщения: 168
Зарегистрирован: 14 авг 2007, 15:16
Откуда: Ростов-на-Дону
прог. языки: C/C++
ФИО: Герасимов Иван

Re: Простая задачка по программированию

Сообщение Denis_Wozniak » 24 мар 2009, 22:37

Да, вроде так.
Грубо говоря не делать много раз "Pos" для одного и того же символа.
Аватара пользователя
Denis_Wozniak
 
Сообщения: 175
Зарегистрирован: 31 дек 2008, 22:47
Откуда: Подмосковье, Ногинск
прог. языки: С, С++, Ну и начинал я в Visual Basic.

Re: Простая задачка по программированию

Сообщение bolt » 24 мар 2009, 23:01

для быстроты надо удалить все буквы которые встречаются один раз

отличная идея! Останутся лишь те, что есть в каждой из фраз. А уж выбрать самую длинную строку не сложно.
bolt
 
Сообщения: 281
Зарегистрирован: 01 дек 2008, 19:21

Re: Простая задачка по программированию

Сообщение Montoya » 25 мар 2009, 00:15

Блин, кому-то не сложно, а у кого-то уже мозг кипит от динамического программирования.....

Добавлено спустя 59 минут 40 секунд:
Вобщем вот, немного переделанный код (с ru.wikipedia.org/wiki/Наибольшая_общая_подпоследовательность), фразы вводить без пробелов
Код: Выделить всёРазвернуть
#include <iostream>
#include <conio.h>
using namespace std;
int main() {
char a[50];
char b[50];
cin>>a;
cin>>b;
int max_len[50][50];
for(int i = strlen(a) - 1; i >= 0; i--)
      {
         for(int j = strlen(b) - 1; j >= 0; j--)
         {
            if(a[i] == b[j])
            {
               max_len[i][j] = 1 + max_len[i+1][j+1];
            }
            else
            {
               max_len[i][j] = max(max_len[i+1][j], max_len[i][j+1]);
            }
         }
      }
      char res[50];
      int k=0;
      for(int i = 0, j = 0; max_len[i][j]!=0 && i<strlen(a) && j<strlen(b); )
      {
         if(a[i] == b[j])
         {
            res[k]=a[i];
            k++;
            i++;
            j++;
         }
         else
         {
            if(max_len[i][j] == max_len[i+1][j])
               i++;
            else
               j++;
         }
      }

cout<<res<<endl;
getch();
}
Аватара пользователя
Montoya
 
Сообщения: 168
Зарегистрирован: 14 авг 2007, 15:16
Откуда: Ростов-на-Дону
прог. языки: C/C++
ФИО: Герасимов Иван

След.

Вернуться в Свободное общение

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 26

cron