Use negative look-ahead expression:
Negative lookahead is indispensable if you want to match something not followed by something else: q(?!u) means q not followed by u
In your case q is %, and u is ([.]?[0-9]+)?[a-zA-Z] (an optional prefix of an optional dot followed by one or more numbers, and a letter suffix).
Demo 1
Note: This expression uses + in the look-ahead section, a feature that does not have universal support. If your regex engine does not take it, set an artificial limit of, say, 20 digits by replacing [0-9]+ with [0-9]{1,20}.
Edit:
What about writing my own parser?
If you need the ultimate speed for this relatively simple regex, use a hand-written parser. Here is a quick example:
for (string str ; getline(cin, str) ; ) {
    bool found = false;
    size_t pos = 0;
    while (!found && (pos = str.find('%', pos)) != string::npos) {
        if (++pos == str.size()) {
            found = true;
            break;
        }
        if (str[pos] == '.') {
            if (++pos == str.size()) {
                found = true;
                break;
            }
            if (!isdigit(str[pos])) {
                found = true;
                break;
            }
        }
        while (isdigit(str[pos])) {
            if (++pos == str.size()) {
                found = true;
                break;
            }               
        }
        found |= !isalpha(str[pos]);
    }
    cout << '"' << str << '"' << " : " << found << endl;
}
Demo 2