$ jq -n '"some string" | gsub("(?<a>[[:lower:]]+)"; "<div>\(.a)</div>")'
"<div>some</div> <div>string</div>"
or
$ jq -n '"some string" | gsub("(?<a>[[:lower:]]+)"; "<div>" + .a + "</div>")'
"<div>some</div> <div>string</div>"
This replaces each run of lowercase letters with the same letters, flanked by <div> and </div>. The capture is done with (?<a>RE) where a is a key name that you can refer to in the replacement using .a (it does not need to be a single letter), and where RE is some expression. You may capture multiple groups with different key names at the same time.
gsub() works like e.g. gsub() in awk and like s///g in Perl, sed, and ed, so it will perform the substitution once for each non-overlapping match of the expression. This is illustrated in my example above where there are two matches of the pattern in the string.
Just to use a more similar example as you:
$ jq -n '"this is a valid JSON string" | gsub("(?<match>valid)"; "<div>" + .match + "</div>")'
"this is a <div>valid</div> JSON string"