LINUX.ORG.RU

Алгоритм не могу вспомнить...


0

0

Есть такой файл:

0
2
30
31
32
33
34
35
360
361
362
363
365
366
367
368
369
37
39
4
5
6
7
80
81
831
832
833
834
835
837
838
839
84
85
86
87
88
89
9


И нужно найти какие 3-ёх значные числа (или на что начинающиеся) не входят в этот список, то есть в нашем случае в этот список не входят:
1*
364
38*
82*
830
836

Всё это сделать без перебора. В реальности этот список состоит из 20-ти значных чисел и в файле болше миллиона строк.

З.Ы. Блин, а в универе что-то похожее помню было...

anonymous

неврубился в суть дела, может тебе бинарное дерево поможет???

Ex ★★
()

off the top of my head:

Реализуешь (или берешь готовую) структуру типа "дерево с 10-ю ветками" (по одной на цифру).

встретив в файле префикс длиной N, создаешь узлы до соотв, глубины:

т.е. 365 => [3]->[6]->[5].

Если при создании узлов глубина ветви увеличивается, считаешь префикс незначимым (т.е. если [3]->[6] уже есть, то префикс 365 никакой новой инфы не несет).

Если все нужные узлы уже существуют, отбрасываешь узлы ниже: мы имеем более общий префикс (т.е. если у нас уже было [3]->[6]->[5]->([3], [4]->[5]), то узлы [3] и [4] в конце, и их подузлы ([5]) удаляем).

И так пока не кончится входной файл.

Затем "инвертируем" полученное дерево: опускается вниз по узлам, и достраиваем отсутствующие префиксы:

если для задачи с длиной 3 после выполнения получилось дерево

[1]->([2], [3]->[4]), то получим:

11*

1(4..9)*

13(1..3)

13(5..9)

(2..9)*

anonymous
()

Во, заморочился, написал. Заняло полчаса, выглядит страшно, но работает. На утечки памяти не проверял. На неправильных данных 
упадет в кору.

#include <iostream>
#include <fstream>

using namespace std;

class TenTree {
private:
    char n;
    TenTree * children[10];
public:
    TenTree(char n_): n(n_) { for (int i = 0; i < 10; ++i) children[i] = 0; };
    TenTree* addChild(char /*n*/);
    TenTree* getChild(char /*n*/);
    void deleteSubTree();
    int numChildren();
    void dump(string);
    void dumpinv(string);
    ~TenTree();
};

TenTree* TenTree::addChild(char cn) {
    if (cn > 9 || cn < 0)
        return 0;
    if (children[cn])
        return children[cn];
    if (numChildren() == 9) {
        deleteSubTree();
        return this;
    }
    TenTree *nc = new TenTree(cn);
    children[cn] = nc;
    return nc;
}
TenTree* TenTree::getChild(char n) {
    return children[n];
}

int TenTree::numChildren() {
    int numch = 0;
    for (int i = 0; i < 10; ++i)
        if (children[i])
            numch++;
    return numch;
}

void TenTree::deleteSubTree() {
    for (int i = 0; i < 10; ++i)  {
        delete children[i];
        children[i] = 0;
    }
}

void TenTree::dump(string prefix)  {
    cout << prefix << char(n + '0') << endl;
    for (int i = 0; i < 10; ++i)
        if (children[i])
            children[i]->dump(prefix+prefix);
}

void TenTree::dumpinv(string prefix) {
    if (!numChildren())
        return;
    for (int i = 0; i < 10; ++i)
        if (children[i])
            children[i]->dumpinv(prefix+char(n + '0'));
        else
            cout << prefix << char(n + '0') << char(i + '0') << "\n";
}

TenTree::~TenTree() {
    deleteSubTree();
}

int main(int argc, char **argv) {
    ifstream rf(argv[1]);
    if (!rf.is_open())
        return 1;
    TenTree top(' '-'0');
    while (!rf.eof()) {
        string l;
        getline(rf, l);
        TenTree *cur = &top;
        for (string::iterator i = l.begin(); i != l.end(); ++i) {
            char n = *i - '0';
            TenTree* child = cur->getChild(n);
            if (!child) {
                child = cur->addChild(n);
            }
            else {
                if (!child->numChildren())
                    break; //hit bottom
            }
            if (!cur->numChildren())
                break; // this char filled last gap
            cur = child;
        }
    }
    rf.close();
    top.dump(".");
    top.dumpinv("");
    return 0;
}

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.