#include <iostream> // библиотке ввода-вывода
#include <string> // библиотека строк
#include <vector> // библиотека векторов (динамических массивов без ограничений памяти)

using namespace std;

class Library {
    vector <vector <string>> books;

    public:

    Library(int quantity){
        books.resize(quantity);
        input_books();
    }

    void input_books(){
        int pages;
        for (int i = 0; i < books.size(); i++){
            cout << "Input count " << i+1 << " book's pages: ";
            cin >> pages;

            cin.get();
            cout << endl;

            if (pages < 1){
                cout << "\nPage's size can't be less than 1\n";
                exit(0);
            }

            books[i].resize(pages);
            input_pages(i);

            cout << endl;
        }
    }

    void input_pages(int index){
        for (int i = 0; i < books[index].size(); i++){
            cout << "\tInput " << i+1 << " page's text\n\t\t";
            getline(cin, books[index][i]);
            cout << endl;
        }
    }

    void output_books(){
        for (int i = 0; i < books.size(); i++){
            cout << i+1 << " book:\n";
            for (int j = 0; j < books[i].size(); j++){
                cout << "\t" << j+1 << " page\n\n";
                cout << "\t\t" << books[i][j];
                cout << "\n\n";
            }
            cout << "\n\n\n";
        }
    }

    int get_book_number(string target_word){
        int target_book;
        int index = -1;
        vector <string> page_words;

        int sum[books.size()];
        for (int i = 0; i < books.size(); i++){
            sum[i] = 0;
        }

        int **count_target_words = new int *[books.size()];
        for (int i = 0; i < books.size(); i++){
            count_target_words[i] = new int [books[i].size()];
        }

        for (int i = 0; i < books.size(); i++){
            for (int j = 0; j < books[i].size(); j++){
                page_words = get_words(books[i][j]);
                count_target_words[i][j] = get_count_target_word(page_words, target_word);
            }
        }

        for (int i = 0; i < books.size(); i++){
            for (int j = 0; j < books[i].size(); j++){
                sum[i] += count_target_words[i][j];
            }
        }

        index = sum[0];
        for (int i = 0; i < books.size(); i++){
            if (index <= sum[i]){
                index = sum[i];
                target_book = i;
            }
        }

        delete_matrix(count_target_words, books.size());

        return target_book;
    }

    void delete_matrix(int **matrix, int iterations){ // удаление матрицы
        for (int i = 0; i < iterations; i++){ // цикл от 0 до iterations
            delete[] matrix[i]; // удаление текущего элемента матрицы
        }
        delete[] matrix; // удаление матрицы
    }

    int get_count_target_word(vector <string> page_words, string target_word){
        int count = 0;

        for (int i = 0; i < page_words.size(); i++){
            if (target_word == page_words[i]){
                count++;
            }
        }

        return count;
    }

    vector <string> get_words(string file_text){
        vector <string> words; // массив для хранения слов строки (используется вектор для устранения ограничения на размер памяти)
        int start = 0; // счётчик начала слова
        int end = 0; // // счётчик конца слова
        int skip_count = 0; // счётчик пропусков

        for (int i = 0; i <= file_text.size(); i++) { // цикл на прохождение строки
            if (skip_count > 0){ // если есть ряд символов без букв
                skip_count--; // уменьшаем счётчик пропусков
                continue; // переходим на следующую итерацию до следующей буквы в строке
            }
            if (ispunct(file_text[i]) || isspace(file_text[i]) || file_text[i] == '\0'){ // если текущий символ строки не является буквой, то
                skip_count = 0; // обнуляем счётчик от нового слова
                end = i; // счётчик окончания равен текущему значению i
                words.push_back(file_text.substr(start, (end-start))); // добавляем в массив слов часть строки от значения счётчика start. 
                // (end - start) нужен для вычисления количества символов
                while (ispunct(file_text[end]) || isspace(file_text[end])){ // пока текущий символ не является буквой,
                    end++; // увеличиваем переменную end
                    skip_count++; // увеличиваем количество пропусков в цикле по количеству итераций end
                } // цикл необходим для перехода к следующему слову, так как в задании не указан разделитель слов.

                start = end; // присваиваем счётчику start значение от end для пропуска не буквенных символов и продолжения работы.
            }
        }

        return words; // возвращаем отсортированный массив
    }

    void delete_words_in_page(int book_index, int page_index, string target_word){
        string new_page_text = "";
        vector <string> page_words = get_words(books[book_index][page_index]);

        for (int i = 0; i < page_words.size(); i++){
            if (page_words[i] == target_word){
                continue;
            }
            new_page_text.append(page_words[i]);
            new_page_text.append(" ");
        }

        books[book_index][page_index] = new_page_text;
    }

    bool check_page_index(int book_index, int page_index){
        return !(page_index < 0 || page_index > books[book_index].size() - 1);
    }
};

int main(){
    string target_word;
    int quantity;
    int book_index;
    int page_index;

    cout << "Input book's quantity: ";
    cin >> quantity;
    cin.get();
    cout << endl;

    if (quantity < 1){
        cout << "\nLibrary's size can't be less than 1.\n";
        return 0;
    }

    Library libre(quantity);

    cout << "Input target word: ";
    cin >> target_word;

    book_index = libre.get_book_number(target_word);

    if (book_index == -1){
        cout << "\nInputed word doesn't find.\n";
        return 0;
    }

    cout << "\nIndex of found book: " << book_index + 1 << endl;


    cout << "\n\nInput book's page: ";
    cin >> page_index;
    cin.get();
    cout << endl << endl;

    if (!libre.check_page_index(book_index, page_index - 1)){
        cout << "Inputed index page doesn't exist.\n";
        return 0;
    }

    libre.delete_words_in_page(book_index, page_index - 1, target_word);

    libre.output_books();

    return 0;
}