diff --git a/cpp/src/arrow/compute/kernels/scalar_string.cc b/cpp/src/arrow/compute/kernels/scalar_string.cc index 451dacf904e84..fbacaab54d621 100644 --- a/cpp/src/arrow/compute/kernels/scalar_string.cc +++ b/cpp/src/arrow/compute/kernels/scalar_string.cc @@ -356,7 +356,7 @@ void TransformBinaryContainsExact(const uint8_t* pattern, int64_t pattern_length prefix_table[0] = -1; for (offset_type pos = 0; pos < pattern_length; ++pos) { // The prefix cannot be expanded, reset. - if (prefix_length >= 0 && pattern[pos] != pattern[prefix_length]) { + while (prefix_length >= 0 && pattern[pos] != pattern[prefix_length]) { prefix_length = prefix_table[prefix_length]; } prefix_length++; @@ -371,14 +371,13 @@ void TransformBinaryContainsExact(const uint8_t* pattern, int64_t pattern_length int64_t pattern_pos = 0; for (int64_t k = 0; k < current_length; k++) { - if (pattern[pattern_pos] == current_data[k]) { - pattern_pos++; - if (pattern_pos == pattern_length) { - bitmap_writer.Set(); - break; - } - } else { - pattern_pos = std::max(0, prefix_table[pattern_pos]); + while ((pattern_pos >= 0) && (pattern[pattern_pos] != current_data[k])) { + pattern_pos = prefix_table[pattern_pos]; + } + pattern_pos++; + if (pattern_pos == pattern_length) { + bitmap_writer.Set(); + break; } } bitmap_writer.Next(); diff --git a/cpp/src/arrow/compute/kernels/scalar_string_test.cc b/cpp/src/arrow/compute/kernels/scalar_string_test.cc index 88a0258ee5f9d..9ed629c1a054f 100644 --- a/cpp/src/arrow/compute/kernels/scalar_string_test.cc +++ b/cpp/src/arrow/compute/kernels/scalar_string_test.cc @@ -320,6 +320,14 @@ TYPED_TEST(TestStringKernels, BinaryContainsExact) { BinaryContainsExactOptions options_repeated{"abab"}; this->CheckUnary("binary_contains_exact", R"(["abab", "ab", "cababc", null, "bac"])", boolean(), "[true, false, true, null, false]", &options_repeated); + + // ARROW-9460 + BinaryContainsExactOptions options_double_char{"aab"}; + this->CheckUnary("binary_contains_exact", R"(["aacb", "aab", "ab", "aaab"])", boolean(), + "[false, true, false, true]", &options_double_char); + BinaryContainsExactOptions options_double_char_2{"bbcaa"}; + this->CheckUnary("binary_contains_exact", R"(["abcbaabbbcaabccabaab"])", boolean(), + "[true]", &options_double_char_2); } TYPED_TEST(TestStringKernels, Strptime) {