The tables in PROGMEM as well is explained in both links I gave: Arduino PROGMEM reference and Nick Gammon about PROGMEM.
When there are only about 10 strings in PROGMEM, perhaps the table can be in RAM.
The strcpy_P and strcat_P has not to do with the table. They just take a pointer and assume that pointer is to PROGMEM to a string. That means that first the table in PROGMEM must be solved before there is a pointer to the string.
With an Arduino Mega 2560 there is often more than enough flash memory, then I use a fixed length for the text and I don't need the table.
const char texts[][36] PROGMEM =
{
"Hello", // 36 - 6 = 30 bytes wasted.
"Hello World, this is a long text.", // almost filled the available space
};
When a text is inside a struct, then there is often a fixed length for the string. Then I can create an array of that struct and no table is needed either. For example a menu can be an array of a struct or a list with a sequence of commands and settings.