Encoding categorical variables so that you do not lose information and do not add non-existent relationships between the categories is fundamental to achieving good performance from your model.
You can not simply LabelEncode your categories because they add non-existent relationships. For example, if you have a feature named 'color' which takes on three values - Red, Blue and Green and you encode Red as 1, Blue as 2 and Green as 3, this will imply relationships such as
$$Red < Blue < Green$$
$$Blue = (Red + Green)/2$$
Because of the curse of dimensionality, you can not use OneHotEncoder as that will inflate your feature space beyond your model's comprehension because of a relatively smaller dataset.
The approach of taking only top k frequently occurring categories will be suboptimal as you loose information. A better approach would be to use a FrequencyEncoder which replaces categories with their frequencies (or counts) of occurrence.
More sophisticated approaches like Target Encoding and Contrast Coding Schemes which take target variable into account when encoding categories are known to perform better in cases of high cardinality categories.
If some of your categories have string values which are not domain-specific you can convert them into meaningful vectors using pre-trained Word2Vec. If any of your categories contain long text (e.g. description of an event), you can train your own Word2Vec on sentences built from values of such a category. By taking a weighted-average of the vectors from a sentence, you can encode sentences.
As far as models are concerned, with the right kind of encoding, Random Forests and Gradient Boosted Machines will work just fine. SVMs and Vanilla Neural Networks are also worth considering. To boost your accuracy you can definitely use XGBoost.