-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathknuth-morris-pratt.cpp
More file actions
109 lines (92 loc) · 2.97 KB
/
knuth-morris-pratt.cpp
File metadata and controls
109 lines (92 loc) · 2.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// KMP Algorithm for String Matching
// Assumes lowercase English letters only
// Time: O(n + m), Space: O(m)
#include <bits/stdc++.h>
using namespace std;
// Builds the Longest Prefix-Suffix (LPS) array for the given pattern.
// lps[i] = length of the longest proper prefix which is also a suffix in pattern[0..i]
vector<int> buildLongestPrefixSuffixArray(const string& pattern)
{
int patternLength = pattern.size();
vector<int> lps(patternLength, 0);
// lengthOfPreviousPrefix stores the length of the last longest prefix-suffix
int lengthOfPreviousPrefix = 0;
int currentIndex = 1;
while (currentIndex < patternLength)
{
if (pattern[currentIndex] == pattern[lengthOfPreviousPrefix])
{
lengthOfPreviousPrefix++;
lps[currentIndex] = lengthOfPreviousPrefix;
currentIndex++;
}
else if (lengthOfPreviousPrefix == 0)
{
// No valid prefix-suffix found, assign 0
lps[currentIndex] = 0;
currentIndex++;
}
else
{
// Try to fallback to a shorter valid prefix-suffix
lengthOfPreviousPrefix = lps[lengthOfPreviousPrefix - 1];
}
}
return lps;
}
// Finds all starting indices in `text` where `pattern` appears using the KMP algorithm
vector<int> findPatternOccurrencesKMP(const string& text, const string& pattern)
{
int textLength = text.size();
int patternLength = pattern.size();
vector<int> occurrences;
if (patternLength == 0)
{
occurrences.push_back(0); // By convention, empty pattern matches at index 0
return occurrences;
}
vector<int> lps = buildLongestPrefixSuffixArray(pattern);
int textIndex = 0; // Pointer for text
int patternIndex = 0; // Pointer for pattern
while (textIndex < textLength)
{
if (text[textIndex] == pattern[patternIndex])
{
textIndex++;
patternIndex++;
}
if (patternIndex == patternLength)
{
// Match found, record the starting index
occurrences.push_back(textIndex - patternLength);
// Continue searching using the LPS array
patternIndex = lps[patternIndex - 1];
}
else if (textIndex < textLength && text[textIndex] != pattern[patternIndex])
{
if (patternIndex != 0)
{
// Fallback in the pattern using the LPS array
patternIndex = lps[patternIndex - 1];
}
else
{
// No prefix match, move to next character in text
textIndex++;
}
}
}
return occurrences;
}
// Sample usage
int main()
{
string text = "ababcabcababc";
string pattern = "abc";
vector<int> matchIndices = findPatternOccurrencesKMP(text, pattern);
for (int index : matchIndices)
{
cout << "Pattern found at index: " << index << endl;
}
return 0;
}