**Use case**

Generate models once and reuse them.

**Describe the solution you'd like**

Add command line options:
```
--save file - write serialized models on disk after training and before generating the data; the user can set --limit to 0 to only train the models and save them without proceeding to data generation;
--load file - instead of training the models, load the prepared models from the file and start generating the data.
```

Serialization format: one byte for version (equals to 0), then simple binary serialization of all the models; the whole file is compressed with ZSTD level 1 using CompressedWriteBuffer (no need to allow any compression options to choose).
? offset_from_begin_of_string + determinator_sliding_window_size - determinator_size : 0;
            const char * determinator_sliding_window_begin = determinator_data + offset_from_begin_of_string - determinator_sliding_window_overflow;
            SipHash hash;
            hash.update(seed);
            hash.update(determinator_sliding_window_begin, determinator_sliding_window_size);
            hash.update(determinator_sliding_window_overflow);
            UInt64 determinator = hash.get64();
            
            double end_probability_multiplier = 0;
            Int64 num_bytes_after_desired_size = (pos - data) - desired_size;
            if (num_bytes_after_desired_size > 0)
                end_probability_multiplier = std::pow(1.25, num_bytes_after_desired_size);
            CodePoint code = it->getMapped().sample(determinator, end_probability_multiplier);
            if (code == END)
                break;
            if (num_bytes_after_desired_size > 0)
            {
                
                
                if (code < 128 && !isAlphaNumericASCII(code))
                    break;
            }
            if (!writeCodePoint(code, pos, end))
                break;
            code_points.push_back(code);
        }
        return pos - data;
    }
};
class StringModel : public IModel