Editorial for Baltic OI '19 P5 - Necklace
Submitting an official solution before solving the problem yourself is a bannable offence.
Let's represent the strings given to the girls by and . A pair of matching necklaces can be found as a concatenation of strings and such that is a substring of and is a substring of .
You might need to reverse first. This converts the following case into the previous one.
2-approximation. As each necklace match consists of two substring matches, at least one of them has to be no shorter than half the length of the necklace. Let be the length of the common suffix of and . Depending on if , is or . To find the longest common substring, we try all possible and for each loop over in increasing order calculating from . This takes time, extra memory.
and . As we have seen, a necklace match can be decomposed into two substring matches by cutting the substrings that give the necklace match at some points. For each possible pair of cut points (all pairs of indexes of and ), we'll find the longest necklace that has these cut points. To find it, we can maximize length of the halves of the necklace separately. Let be the length of longest suffix of , that is a prefix of . Similarly let be the length of longest prefix of that is a suffix of . The longest necklace with cut points has length . To find we can check all lengths naively in , giving an solution overall. Comparing equal length prefixes and suffixes with a rolling polynomial hash gives an solution overall.
Full DP solution. To get a faster solution, we need to find for many pairs of indexes at once. To do this, we will use . If then , , etc. Passing the length from to for all is enough to calculate . Doing this naively would take time. We can optimize it by doing for all and then for all . This gives an solution. To improve the memory usage to you need to analyze the DP transitions carefully.
Full randomized solution. Choose a pair of indexes randomly. Extend to describing the longest substring match that is part of. This takes time proportional to the length of the substring match. If the longest common substring has length , then it takes on average attempts to find it. So, this is a randomized solution to finding the longest common substring.
To find necklaces, we'll generate substring matches this way. For a match of length , we'll try to extend it with strings of length up to to get a necklace match. We can check all lengths naively in , giving an solution. Using a rolling polynomial hash gives an solution. The memory usage is . This solution is on average faster than the DP solution.
Credits
- Task: Jakub Radoszewski (Poland)
- Solutions and tests: Oliver Nisumaa, Andres Unt (Estonia)
Comments