Luogu P8270 [USACO22OPEN] Subset Equality S Solution
The content below was generated entirely by machine translation. Please verify its accuracy. If anything is unclear, consult the Chinese source version.
The reading experience is better on the blog.
1: Problem Statement
You are given two strings, and (the lengths of both and do not exceed ). You are also given some queries (the number of queries does not exceed ). Each query is a subset of the lowercase letters 'a' through 'r'. For every query, determine whether and are equal when they contain only the letters given in the query.
2: Analysis
2.1: Brute Force
It is easy to think of a brute-force method. For each query, consider only the characters contained in the set and compare the two strings. However, this requires traversing the strings again for every query, resulting in complexity ( is both the number of queries and the string length). This method can obtain partial points.
But how can we get the remaining points?
2.2: Simplifying the Problem
Directly solving this problem may be too complicated. We can try simplifying it first and then generalizing the simplified solution to the original problem.
First consider the case where a query contains only two letters. Let them be and . How do we determine whether two strings containing only and are equal?
The first thing to consider is whether the numbers of s and s in the two strings are equal. If either count is different, the two strings must be different.
Next, we need to consider the positions of every and in the strings. If both the positions and counts are correct, the two strings must be equal.
When comparing the positions of and , we certainly cannot directly compare their indices, because we are comparing their positions after keeping only and in the two strings. Their indices must change after other characters are removed.
After removing other characters, the index of each character in a string is actually the number of s before it plus the number of s before it (all other characters have been removed).
Of course, checking the indices of every and in order takes too much time, so we can optimize. For example, it is enough to check that the positions of one of and are all equal. Since the numbers of s and s are equal in both strings, once the positions of one character are determined, the positions of the other are determined as well (every position that is not must be ).
This check can be simplified further. We can consider only the number of s before each . Consider the string "baa". If we use the number of s before an as the index of , the indices of the two s are the same. If we exchange these two s, the string remains the same, so the fact that their indices are equal does not affect our determination of the positions of .
In summary, two strings containing only two characters (assume they are and ) are equal only if:
- The numbers of s and s are equal.
- The number of s before every is equal.
Why do we use this method to determine whether strings are equal?
Because prefix sums let us quickly determine whether two strings containing only two characters are equal.
Considering the two conditions above, to determine whether the number of s before every is equal (where and can be any characters), we need to quickly obtain:
- The number of each character before every position in the original string.
- Every position of each character in the original string.
For the first problem, we can preprocess with prefix sums.
We create two arrays, char_sum_s[i][j] and char_sum_t[i][j], representing how many characters occur from index through index (including ) in strings and , respectively.
The following code computes them:
1 | for(int i = 0; i < s.length(); i++){ |
For the second problem, we create two vectors, char_pos_s[i] and char_pos_t[i], representing all positions of character in strings and , respectively, and compute them using:
1 | for(int i = 0; i < s.length(); i++){ |
2.3: Considering the Original Problem
Now that we can quickly determine whether two strings containing only two characters are equal, let us consider how to apply this to the original problem.
Suppose the two strings were originally equal. There are several ways to make them different:
- Add a character.
- Delete a character.
- Exchange two characters (exchanging two equal characters is equivalent to not exchanging them).
Note: for convenience, call the function that determines whether two strings containing only characters and are equal isok(a, b).
For the first two changes, the count of some character in the two strings must change. Suppose the added or deleted character is . Then isok(a, other character) must return false, because the counts of in and are no longer equal.
Now consider exchanging characters. Suppose the exchanged characters are and . Then isok(a, b) must also return false, because the strings consisting only of and in and must be different.
Therefore, for each query, we only need to enumerate every pair of different characters included in the query and determine whether and are equal when containing only those two characters.
Remember to store every isok(a, b) result so that it does not need to be recalculated later.
2.3: Complexity Analysis
- Preprocessing: .
isok(a, b): because we need to know the number of s before every , we enumerate , so the complexity is the number of s.- Processing all
isok(a, b)results: ( is the string length), because we enumerate every and , and the sum of all their counts is the string length. - Queries: . Since every
isok(a, b)result has already been processed, enumerating two different characters in a query only requires returning the result in time. We enumerate pairs in total.
3: Code
The code contains detailed comments and is relatively fast. See the submission record.
1 | /*Date: 22 - 03-26 16 22 |
Finally, I hope this solution is helpful. If there is anything you do not understand or you find a problem with the solution, feel free to contact me through the comments or a private message.






![[Stanford CS144] Lab 4 Record](/img/CS144/tcp%E7%8A%B6%E6%80%81%E6%B5%81%E8%BD%AC%E5%9B%BE.jpg)