Given a string and a pattern to be matched, how efficiently can the matches be found having zero or one mismatch.
e.g)
S = abbbaaabbbabab
P = abab
Matches are abbb(index 0),aaab(index 4),abbb(index 6),abab(index 10)
I tried to modify KMP algorithm but I'm not sure about the approach.
Please give me idea to proceed with the problem.
Thanks.
Brute Force The algorithm can be designed to stop on either the first occurrence of the pattern, or upon reaching the end of the text.
A string enclosed within double quotes ('"') is used exclusively for pattern matching (patterns are a simplified form of regular expressions - used in most UNIX commands for string matching).
Boyer Moore Algorithm: This algorithm uses best heurestics of Naive and KMP algorithm and starts matching from the last character of the pattern. Using the Trie data structure: It is used as an efficient information retrieval data structure.
The string matching problem is this: given a smaller string P (the pattern) that we want to find occurrences of in T . If P occurs in T at shift i then P[j] = T[i+j] for all valid indices i of P . For example, in the string "ABABABAC", the pattern string "BAB" occurs at shifts 1 and 3.
Ok I found it! I found the best algorithm!
This might sound a bit brave, but as long as the algorithm I am going to propose has both running time O(m + n)
and memory consumption O(m + n)
and the entry data itself has the same properties the algorithm can be optimized only in constant.
I am going to use mix-up between KMP and Rabin Karp algorithms for my solution. Rabin Karp uses rolling hashes for comparing substrings of the initial strings. It requires linear in time precomputing that uses linear additional memory, but from then on the comparison between substrings of the two strings is constant O(1)
(this is amortized if you handle collisions properly).
My solution will not find all the occurrences in the first string that match the second string with at most 1 difference. However, the algorithm can be modified so that for every starting index in the first string if there is such matching at least one of them will be found (this is left to the reader).
Let m
be the length of the second string and n
- the length of the first string. I am going to split the task in two parts: if I am aiming to find a matching with at most one difference, I want to find to substrings of the first string: PREF
is going to be the substring before the single difference and SUFF
the substring after the difference. I want len(PREF) + len(SUFF) + 1 = m
, where PREF
or SUFF
will be artificially shortened if required (when the strings match without difference).
I am going to base my solution on one very important observation: suppose there is a substring of the first string starting at index i
with length m
that matches the second string with at most one difference. Then if we take PREF
as long as possible there will still be solution for SUFF
. This is obvious: I am just pushing the difference as much to the end as possible.
And now follows the algorithm itself. Start off with usual KMP. Every time when the extension of the prefix fails and the fail links are to be followed, first check whether if you skip the next letter the remaining suffix will match the remaining of the second string. If so the sought match with at most one character difference is found. If not - we go on with the ordinary KMP making the Rabin Karp check every time a fail link is to be followed.
Let me clarify further the Rabin Karp check with an example. Suppose we are at certain step of the KMP and we have found that first.substring[i, i + k - 1]
matches the first k
letters of the second string. Suppose also that the letter first[i + k]
is different from second[k]
. Then you check whether first.substring[i + k + 1, i + m - 1]
matches exactly second.substring[k + 1, m - 1]
using Rabin Karp. This is exactly the case in which you have extended the starting prefix form index i
as much as possible and you try now whether there is a match with at most one difference.
Rabin Karp will be used only when a fail link is followed, which moves the starting index of the prefix with at least one, which means that at most O(n)
Rabin Karp calls are used, every one with complexity O(1)
for a total of linear complexity.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With