@@ -85,61 +85,75 @@ OverlapKind
85
85
MutableTerm::checkForOverlap (const MutableTerm &other,
86
86
MutableTerm &t,
87
87
MutableTerm &v) const {
88
- // If the other term is longer than this term, there's no way
89
- // we can overlap.
90
- if (other.size () > size ())
91
- return OverlapKind::None;
92
-
93
- auto first1 = begin ();
94
- auto last1 = end ();
95
- auto first2 = other.begin ();
96
- auto last2 = other.end ();
97
-
98
- // Look for an overlap of the first kind, where the other term is
99
- // wholly contained in this term.
100
- //
101
- // A.B.C.D.E
102
- // X.Y.Z
103
- // X.Y.Z
104
- // X.Y.Z
105
- while (last1 - first1 >= last2 - first2) {
106
- if (std::equal (first2, last2, first1)) {
107
- // We have an overlap of the first kind, where
108
- // this == TUV and other == U.
109
- //
110
- // Get the subterms for T and V.
111
- t = MutableTerm (begin (), first1);
112
- v = MutableTerm (first1 + other.size (), end ());
113
- return OverlapKind::First;
114
- }
88
+ assert (!empty ());
89
+ assert (!other.empty ());
90
+
91
+ if (*this == other) {
92
+ // If this term is equal to the other term, we have an overlap.
93
+ t = MutableTerm ();
94
+ v = MutableTerm ();
95
+ return OverlapKind::First;
96
+ }
115
97
116
- ++first1;
98
+ if (size () > other.size ()) {
99
+ // If this term is longer than the other term, check if it contains
100
+ // the other term.
101
+ auto first1 = begin ();
102
+ while (first1 <= end () - other.size ()) {
103
+ if (std::equal (other.begin (), other.end (), first1)) {
104
+ // We have an overlap.
105
+ t = MutableTerm (begin (), first1);
106
+ v = MutableTerm (first1 + other.size (), end ());
107
+
108
+ // If both T and V are empty, we have two equal terms, which
109
+ // should have been handled above.
110
+ assert (!t.empty () || !v.empty ());
111
+ assert (t.size () + other.size () + v.size () == size ());
112
+
113
+ return OverlapKind::First;
114
+ }
115
+
116
+ ++first1;
117
+ }
117
118
}
118
119
119
- // Look for an overlap of the second kind, where a prefix of the
120
- // other term is equal to some suffix of this term.
120
+ // Finally, check if a suffix of this term is equal to a prefix of
121
+ // the other term.
122
+ unsigned count = std::min (size (), other.size ());
123
+ auto first1 = end () - count;
124
+ auto last2 = other.begin () + count;
125
+
126
+ // Initial state, depending on size() <=> other.size():
121
127
//
122
- // A.B.C.D.E
123
- // X.Y
124
- // X
125
- while (first1 != last1) {
126
- --last2;
128
+ // ABC -- count = 3, first1 = this[0], last2 = other[3]
129
+ // XYZ
130
+ //
131
+ // ABC -- count = 2, first1 = this[1], last2 = other[2]
132
+ // XY
133
+ //
134
+ // ABC -- count = 3, first1 = this[0], last2 = other[3]
135
+ // XYZW
127
136
128
- if (std::equal (first1, last1, first2)) {
129
- // We have an overlap of the second kind, where
130
- // this == TU and other == UV.
131
- //
132
- // Get the subterms for T and V.
137
+ // Advance by 1, since we don't need to check for full containment
138
+ ++first1;
139
+ --last2;
140
+
141
+ while (last2 != other.begin ()) {
142
+ if (std::equal (other.begin (), last2, first1)) {
133
143
t = MutableTerm (begin (), first1);
134
- assert (!t.empty ());
135
144
v = MutableTerm (last2, other.end ());
145
+
146
+ assert (!t.empty ());
147
+ assert (!v.empty ());
148
+ assert (t.size () + other.size () - v.size () == size ());
149
+
136
150
return OverlapKind::Second;
137
151
}
138
152
139
153
++first1;
154
+ --last2;
140
155
}
141
156
142
- // No overlap found.
143
157
return OverlapKind::None;
144
158
}
145
159
0 commit comments