Программа для поиска анаграмм С++

75
21 февраля 2022, 13:40

Дано слово и словарь. Словарь должен быть задан файлом *txt. Необходимо найти все слова из словаря, которые можно составить из букв данного слова(Найти все анаграммы), и вывести их в порядке уменьшения длины. В качестве словаря можно использовать любой текстовый файл с любыми словами, но желательно использовать словарь со словами русского языка. Ниже код выводит количество анаграмм в словаре, не могу сделать по заданию..

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#define DIFFERENCE ('A' - 'a') // разность регистров
using namespace std;
bool IsBigAlpha(char a) {
    return (a >= 'A' && a <= 'Z');
}
bool IsSmalAlpha(char a) {
    return (a >= 'a' && a <= 'z');
}
string edit(const string &str) { // приводим всё к нижнему регистру и  убираем лишние символы
    string rez = "";
    for(char a : str) {
        if (IsBigAlpha(a)) a -= DIFERENSE;
        if (IsSmalAlpha(a)) rez += a;
    }
    return rez;
}
bool comp(const pair<string, string> &a, const pair<string, string> &b) { // сравнитель по второй строке
    return a.second < b.second;
}
int main() {
    vector <pair<string, string>> words; // словарь
    string str;
    while (getline(cin, str, '\n')) {
        pair<string, string> word; // слово
        word.first = str;
        word.second = edit(str);
        sort(word.second.begin(), word.second.end()); // сортируем буквы в слове
        words.push_back(word);
    }
    sort(words.begin(), words.end(), comp); // сортируем словарь по анаграммам
    vector <int> indeces; // массив индексов
    int Count = 0, MaxCount = 0, n = words.size();
    for (int i = 1; i < n; i++) {
        if (words[i-1].second == words[i].second) Count++; 
        else {
            if (Count > MaxCount) { 
                MaxCount = Count;
                indeces.clear();
                indeces.push_back(i-1);
            } else if (Count == MaxCount) indeces.push_back(i-1);
            Count = 0;
        }
    }
    if (Count > MaxCount) {  // обрабатываем последний найденный набор анаграмм
                MaxCount = Count;
                indeces.clear();
                indeces.push_back(n-1);
    } else if (Count == MaxCount) indeces.push_back(n-1);
    bool first = 1;
    for (int index : indeces) { // выводим
        if (!first) cout << endl << "---------------" << endl;
        else first = 0;
        for (int i = 0; i <= MaxCount; i++) {
            if (i != 0) cout << endl;
            cout << words[index - i].first;
        }
    }
    return 0;
}
Answer 1

Ваша задача решается через permutation входного слова и пересечение 2-х контейнеров

в примере вместо чтения файлов просто вектор строк)

Вот алгоритм :

1) Входное слово очищается от пробелов(если они есть), далее все это permutation с добавлением пробела после каждого цикла permutation и пишется в unordered_set (пробел добавляется для получения всех разбиений слова прим. вх: ap вых: ap, pa, a p, p a) тут надо не забыть сделать trim + multispace на входные данные если это надо)

2) Дампите словарь в контейнер и находите пересечение permutation и словаря

UPD: у функции AllWordPermutation есть 2 режима работы связанной с генерацией данных.

в 1 режиме (флаг true) - будут генерироваться только отдельные слова по типу вх. ab ; исх a, ab, b, ba 2 режим не разбивает строки на лексемы и на выходе будут "a b" "ba" "ab"

UPD2: AllWordPermutation2 теперь реализует метод Heap'a

#include <iostream>
#include <vector>
#include <algorithm>
#include <vector>
#include <iterator>
#include <unordered_set>
#include <string>
#include <sstream>

void StringToLower(std::string& line) {
    std::transform(std::begin(line), std::end(line), std::begin(line),
                   [](unsigned char c){ return std::tolower(c); });
}

std::string trim(std::string str, bool multi_space = true) {
    auto trim_left_it{std::find_if(std::begin(str), std::end(str), [](char ch){return !std::isspace(ch);})};
    str.erase(std::begin(str), trim_left_it);
    auto trim_right_it{std::find_if(std::rbegin(str), std::rend(str), [](char ch){return !std::isspace(ch);})};
    str.erase(trim_right_it.base(), std::end(str));
    if (multi_space) {
        std::string res;
        std::unique_copy(std::begin(str), std::end(str),
                        std::back_insert_iterator<std::string>(res),
                        [](char a,char b){ return isspace(a) && isspace(b);});
        return res;
    }
    return str;
}

std::vector<std::string> split_str(const std::string& str) {
    std::vector<std::string> tokens;
    std::size_t prev = 0, pos = 0;
    do {
        pos = str.find(' ', prev);
        if (pos == std::string::npos) {
            pos = str.length();
        }
        std::string token = str.substr(prev, pos-prev);
        if (!token.empty()) {
            tokens.push_back(token);
        }
        prev = pos + 1;
    } while (pos < str.length() && prev < str.length());
    return tokens;
}

std::vector<std::string> AllWordPermutation(std::string word, bool separate_all = true) {
    word.erase(std::remove(std::begin(word), std::end(word), ' '), std::end(word));
    std::sort(std::begin(word), std::end(word));
    std::unordered_set<std::string> perm_data_set;
    if (!separate_all) {
        word.append(word.length() - 1, ' ');
        do {
            perm_data_set.insert(trim(word));
        } while (std::next_permutation(std::begin(word), std::end(word)));
    } else {
        for (auto ch : word) {
            perm_data_set.insert(std::string{ch});
        }
        word.append(word.length() - 2, ' ');
        std::string tmp_word;
        do {
            auto splited{split_str(trim(word))};
            for (auto sub_word : splited) {
                perm_data_set.insert(trim(sub_word));
            }
        } while (std::next_permutation(std::begin(word), std::end(word)));
    }
    std::vector<std::string> ret{std::begin(perm_data_set), std::end(perm_data_set)};
    std::sort(std::begin(ret), std::end(ret));
    return ret;
}
std::vector<std::string> AllWordPermutation2(std::string s) {
    s.erase(std::remove(std::begin(s), std::end(s), ' '), std::end(s));
    std::sort(std::begin(s), std::end(s));
    std::unordered_set<std::string> perm_data_set;
    for (auto ch : s) {
            perm_data_set.insert(std::string{ch});
    }
    s.append(s.length() - 2, ' ');
    std::function<void(char*, std::size_t, std::size_t, std::unordered_set<std::string>&)> heapPermutation;
    auto ins{[&](char* a, std::size_t n, std::unordered_set<std::string>& perm_data_set)
                    {
                        auto splited{split_str(trim(std::string{a, a + n}))};
                        for (auto sub_word : splited) {
                             perm_data_set.insert(trim(sub_word));
                        }
                    }};
    heapPermutation = [&] (char* a,std::size_t size, std::size_t n, std::unordered_set<std::string>& perm_data_set) {
                                if (size == 1) {
                                    ins(a, n, perm_data_set);
                                    return; 
                                } 
                                for (std::size_t i{0}; i < size; ++i) { 
                                    heapPermutation(a, size-1, n, perm_data_set);
                                    if ((size % 2) == 1) {
                                        std::swap(a[0], a[size-1]); 
                                    } else {
                                        std::swap(a[i], a[size-1]); 
                                    }
                                } 
                           };
    heapPermutation(&s[0], s.length(), s.length(), perm_data_set);
    std::vector<std::string> ret{std::begin(perm_data_set), std::end(perm_data_set)};
    std::sort(std::begin(ret), std::end(ret));
    return ret;
}

std::vector<std::string> GetIntersection(std::vector<std::string>& perm_data, std::vector<std::string>& dict) {
    if (!std::is_sorted(std::begin(perm_data), std::end(perm_data))) {
        std::sort(std::begin(perm_data), std::end(perm_data));
    }
    if (!std::is_sorted(std::begin(dict), std::end(dict))) {
        std::sort(std::begin(dict), std::end(dict));
    }
    std::vector<std::string> intersection_ret;
    std::set_intersection(std::begin(perm_data), std::end(perm_data),
                          std::begin(dict), std::end(dict),
                          std::back_inserter(intersection_ret));
    return intersection_ret;
}

int main() {
    std::string word{"melon"};
    StringToLower(word);
    std::vector<std::string> dict{"sdas", "lemon", "dog", "stone", "olmen", "yeah", "hoho", "melon", "olnem", "no mel", "nom el", "l o n m e"};
    std::for_each(std::begin(dict), std::end(dict), StringToLower);
    std::cout << "Word : " << word << std::endl;
    std::cout << "Dict : ";
    std::copy(std::begin(dict), std::end(dict), std::ostream_iterator<std::string>{std::cout, " "});
    std::cout << std::endl;
    std::cout << std::endl;
    auto perm_data{AllWordPermutation(word, true)};
    std::cout << perm_data.size() << " combinations generated!" << std::endl;
    auto intersection_ret{GetIntersection(perm_data, dict)};
    std::copy(std::begin(intersection_ret), std::end(intersection_ret), std::ostream_iterator<std::string>{std::cout, "\t"});
    std::cout << std::endl << std::endl;

    auto perm_data2{AllWordPermutation2(word)};
    std::cout << perm_data2.size() << " combinations generated!" << std::endl;
    auto intersection_ret2{GetIntersection(perm_data2, dict)};
    std::copy(std::begin(intersection_ret2), std::end(intersection_ret2), std::ostream_iterator<std::string>{std::cout, "\t"});
    std::cout << std::endl;
    return 0;
}
Answer 2

На самом деле все намного легче:

разделяй и влавствуй

Нужно где то хранить заданное слово, чтобы проверять выполнение условия:

using std::string;
class Pred {
    const string s;
public:
    Pred(const string& basic)
        : s(basic) {}
    //если нет хоть одного символа из слова в нашей строке
    //то вернем ложь
    bool operator()(const string& str)
    {
        for (const char c : str) {
            if (s.find(c) == s.npos)
                return false;
        }
        return true;
    }
};

Теперь нужно читать из файла слова в какой нибудь контейнер, а потом сортировать согласно требованию:

auto get_set(std::istream& file, const string& str)
{  
    std::vector<string> v;
    using Input = std::istream_iterator<string>;
    std::copy_if(Input(file), Input(), std::back_inserter(v), Pred(str));
    std::sort(v.begin(), v.end(), [](const string& s1, const string& s2)
        { return s1.size() < s2.size(); });
    return v;
}

Программа будет простая. Например:

auto seq = get_set(input_file, "some_string");
for (auto& s : seq)
    cout << s << '\n';  
READ ALSO
jquery подставить ссылку страницы

jquery подставить ссылку страницы

Подскажите пожалуйста, есть такой код:

117
Вывести json как поле mysql

Вывести json как поле mysql

Мне нужно вывести json как поле mysql, то есть допустим у меня есть такой json который хранится в значении одного из столбцов mysql

145
Транзакции MySQL или как застолбить будущее

Транзакции MySQL или как застолбить будущее

Допустим, имеем следующие записи:

106
NulPointerException on ActionListener

NulPointerException on ActionListener

Подскажите пожалуйстаДан код следующий(из книги)

101