[C++] Array-based Solution Explained, ~98% Time, ~70% Space
Cute one.\n\nAnd it had me playing for a bit, then I finally realised that I wanted to keep track of what character each word was expecting and then just parse 
Cute one.\n\nAnd it had me playing for a bit, then I finally realised that I wanted to keep track of what character each word was expecting and then just parse through `s`, advancing them until I complete each word.\n\nThe tricky part was how to remove words with non-matching characters and the ones I already completed from the checks, so I came up with the idea of store them in a hashmap, with the next character as a value and a vector of words to progress and the position of their next character pairs as a value.\n\nI assigned `wordPos` to be said kind of pair, then I moved on creating more support variables:\n* `res` is our counter variable that we will increase for each match - initially set to `0`;\n* `nextChar` is a helper we will use later to store the next character of each word;\n* `q` is where we will store our words, bucketed by next character.\n\nAnd populating `q` is what we will do first, looping through every `word` in `words` and adding a `{word, 1}` pair to each first bucket (picking the first character, `word[0]`, as a key for said bucket); we will add `1` as a second element of the pair because this will always be the index of the next character we are going to go looking for.\n\nWe will then parse each character `c` in `s` and:\n* we will define `curr` as `q[c]`;\n* we will declare `tmp` as a variable of type `wordPos` to replace `q[c]` for the next run;\n* for each element `el` in `curr` we will:\n\t* extract `str` and `pos` from `el`;\n\t* check if we are done parsing the current string `str` (ie: `pos == str.size()` and, in case:\n\t\t* increase `res` by `1`;\n\t\t* `continue` with the next `el`;\n\t* alternatively, we will assign `str[pos]` to `nextChar` and:\n\t* if `nextChar == c` add the same string `str` and `pos + 1` to `tmp`;\n\t* alternatively, we will add the same pair to `q[nextChar]`;\n* finally, we will update `q[c]` to be now `tmp`.\n\nOnce done, we can return `res` :)\n\nThe code:\n\n```cpp\nusing wordPos = vector<pair<string, int>>;\n\nclass Solution {\npublic:\n    int numMatchingSubseq(string s, vector<string>& words) {\n        // support variables\n        int res = 0;\n        char nextChar;\n        unordered_map<char, wordPos> q;\n        // initialising q\n        for (auto &word: words) q[word[0]].push_back({word, 1});\n\t\t// parsing s to find matching words\n        for (char c: s) {\n            // current set of words at c\n            auto curr = q[c];\n            // next value for c\n            wordPos tmp;\n            // parsing all the pairs in curr\n            for (auto el: curr) {\n                auto [str, pos] = el;\n                // checking if the word is now complete\n                if (pos == str.size()) {\n                    res++;\n                    continue;\n                }\n                nextChar = str[pos];\n                // checking if the next character is still c, in which case we had to tmp\n                if (nextChar == c) tmp.push_back({str, pos + 1});\n                // alternatively, we add it to the proper existing bucket\n                else q[nextChar].push_back({str, pos + 1});\n            }\n            // updating q[c]\n            q[c] = tmp;\n        }\n        return res;\n    }\n};\n```\n\nThen I told myself "wait, but why an `unordered_map`? With an array I can do just fine, but much faster; so I refactored just one line:\n\n```cpp\nunordered_map<char, wordPos> q;\n```\n\nBecame:\n\n```cpp\nwordPos q[123];\n```\n\nAnd, yes: much faster \uD83C\uDF89 !\n\nEven better taking strings as references, with:\n\n```cpp\nauto [str, pos] = el;\n```\n\nBecoming:\n\n```cpp\nstring &str = el.first;\nint pos = el.second;\n```\n\nAnd the memory consumption went down a lot too!\n\nBut, wait a moment again - do we really need to carry the strings around?\n\nWell, probably not, with an index just being enough, so refactored again (with some minor cleanup), this time storing in `wordPos` 2 positions - the one of the word in `words` and the one of the next character to parse (just like before):\n\n```cpp\nusing wordPos = vector<pair<int, int>>;\n\nclass Solution {\npublic:\n    int numMatchingSubseq(string s, vector<string>& words) {\n        // support variables\n        int res = 0, len = words.size();\n        char nextChar;\n        wordPos q[123];\n        // initialising q\n        for (int i = 0; i < len; i++) q[words[i][0]].push_back({i, 1});\n\t\t// parsing s to find matching words\n        for (char c: s) {\n            // next value for c\n            wordPos tmp;\n            // parsing all the pairs in curr\n            for (auto &el: q[c]) {\n                auto [wordPos, pos] = el;\n                // checking if the word is now complete\n                if (pos == words[wordPos].size()) {\n                    res++;\n                    continue;\n                }\n                nextChar = words[wordPos][pos];\n                // checking if the next character is still c, in which case we had to tmp\n                if (nextChar == c) tmp.push_back({wordPos, pos + 1});\n                // alternatively, we add it to the proper existing bucket\n                else q[nextChar].push_back({wordPos, pos + 1});\n            }\n            // updating q[c]\n            q[c] = tmp;\n        }\n        return res;\n    }\n};\n```
['C', 'C++']