I know it's already explained in a lot of detail in the other answer (including a better explanation of the regex used in general), but I recently came across this regex without explanation, so I've added some comments myself for it. I figured I'd also share it here for others to see.
The first thing to note is that the regex uses unary for the integers. So String s = new String(new char[n]);
in the Java code will convert an integer n
into a String of that many ('\0'
) characters. Which character this string contains isn't important, it's the length that matters for unary. (An alternative in Java 11+ could for example have been String s = "x".repeat(n);
, and it would still work as intended.)
As for the regex itself:
"(?x) .? | ( \\2?+ (\\1|^.) )* .." # Since this is a Java-String, where the `\` are escaped
# as `\\` and `String#matches` also implicitly adds a
# leading/trailing `^...$` to regex-match the entire
^(?x) .? | ( \2?+ (\1 |^.) )* ..$ # String, the actual regex will be this:
# The `(?x)` is used to enable comments and whitespaces,
# so let's ignore those for now:
^.?|(\2?+(\1|^.))*..$
( )* # First capture group repeated 0 or more times.
# On each iteration it matches one Fibonacci number.
|^. # In the first iteration, we simply match 1 as base case.
# Afterwards, the ^ can no longer match, so the
# alternative is used.
\2?+ # If possible, match group 2. This ends up being the
# Fibonacci number before the last. The reason we need
# to make his optional is that this group isn't defined
# yet in the second iteration. The reason we have the `+`
# is to prevent backtracking: if group 2 exists, we
# *have* to include it in the match, otherwise we would
# allow smaller increments.
(\1| ) # Finally, match the previous Fibonacci number and store
# it in group 2 so that it becomes the second-to-last
# Fibonacci number in the next iteration.
# This in total ends up adding Fibonacci numbers starting
# at 1 (i.e. 1,2,3,5,8,... will add up to 3,6,11,19,...
.. # They are all two less than the Fibonacci numbers, so
# we add 2 at the end.
# Now it's only missing the 0 and 1 of the Fibonacci
.?| # numbers, so we'll account for those separately