Regular Bracket sequence
The correct sequence of the bracket is a string consisting entirely of characters with "brackets" (often considered only parentheses, but this will be considered and the general case of several types of brackets), where each closing brace exists a corresponding opening (and of the same type).
Here we consider the classic problem parenthesis on the right sequence (for brevity hereinafter simply "order") to check the correctness of the number of sequences, all sequences generated by finding the lexicographically next sequence determination
-th sequence in the sorted list of all sequences, and, conversely, determination sequence number. Each of the problems addressed in two ways - when the brackets are allowed only one type, and when several types.
Check for correct
Suppose first allowed only one type of bracket, then check for correct sequence can be a very simple algorithm. May
- is the current number of open parentheses.Initially
. We will move from left to right on the line, if the current opening bracket, the increase
in the unit, otherwise reduce. If in this case when it turns negative, or at the end of the algorithm
is different from zero, this string is not correct bracketing sequence is different.
If allowed several types of brackets, then the algorithm you want to change. Instead, the meter
should create a stack, in which we put the parentheses as they become available. If the current character in the string - opening bracket, then we place it on the stack, and if the closing - then check that the stack is not empty, and that on the top bracket is the same type as the current one, and then We reach this bracket from the stack. If any of the conditions are not fulfilled, or at the end of the algorithm the stack was not empty, then the sequence is not the correct bracketing, or is.
Thus, both of these problems, we learned to solve in time
.
Number of sequences
formula
The number of correct bracket sequence with one type of brackets can be calculated as the number of Catalan . Those. if there is a
pair of brackets (line length
), the number will be:
Suppose now that there is not one, and
types of brackets. Then, each pair of brackets independently of the others may take one of the
types, so we get the following formula:
dynamic programming
On the other hand, this problem can be approached from the point of view of dynamic programming . Let
- the number of correct bracket sequence of
pairs of brackets. Note that in the first position will always stand open parenthesis. It is clear that in this pair of brackets is some correct bracket sequence; similarly, after this pair of brackets is also correct bracket sequence. Now, to calculate
, Let's brute over how many pairs of brackets
will be inside the first pair, then, respectively,
a pair of brackets will stand after the first pair. Therefore, the formula for
is:
The initial value of the recursion formula - it
.
Finding all sequences
Sometimes you need to find and display all the correct bracket sequence specified length
(in this case
- it is the length of string).
To do this, you can start with the lexicographically first sequence
, and then find the lexicographically each time the following sequence using the algorithm described in the next section.
But if the restrictions are not very large (
up to
), you can do much easier. We find all kinds of permutations of these brackets (this is useful next_permutation () function), they will be
, and each check on the correctness of the algorithm described above, in the case of correctness derive the current sequence.
Also, the process of finding all sequences can be issued in the form of a recursive enumeration with clipping (that ideally can be adjusted according to the speed of the first algorithm).
Finding the next sequence
Here we consider only the case of one type of brackets.
For a given proper bracketing sequence is required to find the correct sequence of the bracket, which is next in the lexicographical order after the current (or to give "No solution", if such exists).
It is clear that the whole algorithm is as follows: find a rightmost opening parenthesis, that we have the right to change at closing (as to the correctness of this place is not broken), and the whole line is replaced by the lexicographically minimum rest right: that is, as a opening parenthesis, then all of the remaining closing brackets. In other words, we try to remain unchanged as the longest prefix of the original sequence, and this sequence the suffix is replaced by the lexicographically minimum.
It remains to learn to look for that same position of the first changes. To do this, we will go on the line from right to left, and maintain a balance
of open and closed brackets (at the meeting opening bracket will decrease
, and at the closing - increase). If at any point we are on the opening parenthesis, and the balance after the processing of the character is greater than zero, then we have found the right-most position from which we can begin to change the sequence (in fact,
means that the left has not closed yet parenthesis) . We put the current position closing parenthesis, then the maximum possible number of opening brackets, and then all of the remaining closing brackets - the answer is found.
If we watched the whole line and have not found a suitable position, the current sequence - the maximum, and there is no answer.
The implementation of the algorithm:
string s; cin >> s; int n = (int) s.length(); string ans = "No solution"; for (int i=n-1, depth=0; i>=0; --i) { if (s[i] == '(') --depth; else ++depth; if (s[i] == '(' && depth > 0) { --depth; int open = (n-i-1 - depth) / 2; int close = n-i-1 - open; ans = s.substr(0,i) + ')' + string (open, '(') + string (close, ')'); break; } } cout << ans;
Thus, we have solved this problem for
.
sequence Number
Here, let
- the number of pairs of brackets in the sequence. Required for a given proper bracketing sequence to find its number in the list lexicographically ordered the correct bracket sequence.
Let us learn to consider supporting the dynamics of
which
- the length of the bracket sequence (it "semiregular": all the closing bracket has an opening pair, but not all open parentheses are closed),
- the balance (ie the difference between the number of opening and closing brackets),
- the number of such sequences.When calculating these dynamics, we believe that the brackets are only one type.
Read this dynamic as follows. Let
- the value that we want to calculate. If
the answer is clear right away:
all the rest
. Now suppose that
, then mentally Let's brute over, which was equal to the last character of this sequence. If he is '(' something to that character, we were able to
. If it is equal to ')', then it was the previous state
. Thus we get the formula:
(assuming that all values
at negative
zero). Thus, this dynamic can we count for
.
Let us now turn to the solution of the problem.
First, let only allowed braces one type. Zavedёm counter
nesting in parentheses, and will move in sequence from left to right. If the current symbol
(
) is' ( 'we increase
at 1 and go to the next character. If the current character is')', then we must add to the response
, thereby taking into account that the symbol would be in this position ' ( '(which would lead to lower lexicographical sequence than the current), then we reduce
by one.
Suppose now that the brackets are allowed multiple
types. Then, when considering the current character
to the conversion
we need to go through all brackets that are less than the current character, to try to put the bracket at the current position (thereby obtaining a new balance
), and and add to account number corresponding to the "tails" - completions (which have a length
, balance
and
types of brackets). It is alleged that the formula for this quantity has the form:
This formula is derived from the following considerations. First, we "forget" about the fact that there are several types of braces, and just take the answer from
. Now calculate how to change an answer because of the
types of brackets. We have an
undefined position of which
are staples, closing some of the public before - hence, the type of bracket, we can not be varied. But all the other brackets (and they will
steam) can be of any
type, so the answer is multiplied by the power of the number
.
Finding
th sequence
Here, let
- the number of pairs of brackets in the sequence. In this problem on the set
you want to search
-s correct bracket sequence in the list lexicographically ordered sequence.
As in the previous section, we calculate the dynamics
- the number of correct bracket sequence length
with the balance
.
Suppose first allowed only brackets of type.
We move on the characters of the string, with
th at
th. As in the previous problem, let us have a counter
- current depth of nesting in parentheses. In each of the current position will be possible to touch a symbol - an opening parenthesis or closing. Suppose we want to put an opening parenthesis here, then we have to look at the value
. If it is
, then we put in the current position of the opening bracket, increasing
by one and move on to the next character.Otherwise, we will take away from the
value
, put the closing bracket and reduce the value
. In the end, we obtain the required sequence of the bracket.
The implementation of the Java language using long arithmetic:
int n; BigInteger k; // входные данные BigInteger d[][] = new BigInteger [n*2+1][n+1]; for (int i=0; i<=n*2; ++i) for (int j=0; j<=n; ++j) d[i][j] = BigInteger.ZERO; d[0][0] = BigInteger.ONE; for (int i=0; i<n*2; ++i) for (int j=0; j<=n; ++j) { if (j+1 <= n) d[i+1][j+1] = d[i+1][j+1].add( d[i][j] ); if (j > 0) d[i+1][j-1] = d[i+1][j-1].add( d[i][j] ); } String ans = new String(); if (k.compareTo( d[n*2][0] ) > 0) ans = "No solution"; else { int depth = 0; for (int i=n*2-1; i>=0; --i) if (depth+1 <= n && d[i][depth+1].compareTo( k ) >= 0) { ans += '('; ++depth; } else { ans += ')'; if (depth+1 <= n) k = k.subtract( d[i][depth+1] ); --depth; } }
Suppose now allowed more than one, and
types of brackets. Then the algorithm solutions will be different from the previous case only in that we have to multiply the value
by an amount
to take into account that this balance can be brackets of various types, and the pair of parentheses in this balance will only be
because
the brackets are closing for opening brackets that are that is the residue (and their types because we can not be varied).
The implementation of the Java language in the case of two types of brackets - round and square:
int n; BigInteger k; // входные данные BigInteger d[][] = new BigInteger [n*2+1][n+1]; for (int i=0; i<=n*2; ++i) for (int j=0; j<=n; ++j) d[i][j] = BigInteger.ZERO; d[0][0] = BigInteger.ONE; for (int i=0; i<n*2; ++i) for (int j=0; j<=n; ++j) { if (j+1 <= n) d[i+1][j+1] = d[i+1][j+1].add( d[i][j] ); if (j > 0) d[i+1][j-1] = d[i+1][j-1].add( d[i][j] ); } String ans = new String(); int depth = 0; char [] stack = new char[n*2]; int stacksz = 0; for (int i=n*2-1; i>=0; --i) { BigInteger cur; // '(' if (depth+1 <= n) cur = d[i][depth+1].shiftLeft( (i-depth-1)/2 ); else cur = BigInteger.ZERO; if (cur.compareTo( k ) >= 0) { ans += '('; stack[stacksz++] = '('; ++depth; continue; } k = k.subtract( cur ); // ')' if (stacksz > 0 && stack[stacksz-1] == '(' && depth-1 >= 0) cur = d[i][depth-1].shiftLeft( (i-depth+1)/2 ); else cur = BigInteger.ZERO; if (cur.compareTo( k ) >= 0) { ans += ')'; --stacksz; --depth; continue; } k = k.subtract( cur ); // '[' if (depth+1 <= n) cur = d[i][depth+1].shiftLeft( (i-depth-1)/2 ); else cur = BigInteger.ZERO; if (cur.compareTo( k ) >= 0) { ans += '['; stack[stacksz++] = '['; ++depth; continue; } k = k.subtract( cur ); // ']' ans += ']'; --stacksz; --depth; }