protected function lookup_word_pattern( $key, callable $strlen, callable $str_split ) {
		if ( null === $this->pattern_trie ) {
			return []; // abort early.
		}

		// Add underscores to make out-of-index checks unnecessary,
		// also hyphenation is done in lower case.
		$search        = '_' . $key . '_';
		$search_length = $strlen( $search );
		$chars         = $str_split( $search );
		$word_pattern  = [];

		for ( $start = 0; $start < $search_length; ++$start ) {
			// Start from the trie root node.
			$node = $this->pattern_trie;

			// Walk through the trie while storing detected patterns.
			for ( $step = $start; $step < $search_length; ++$step ) {
				// No further path in the trie.
				if ( ! $node->exists( $chars[ $step ] ) ) {
					break;
				}

				// Look for next character.
				$node = $node->get_node( $chars[ $step ] );

				// Merge different offset values and keep maximum.
				foreach ( $node->offsets() as $pattern_offset ) {
					$value  = $pattern_offset[0];
					$offset = $pattern_offset[1] + $start - 1;

					$word_pattern[ $offset ] = isset( $word_pattern[ $offset ] ) ? max( $word_pattern[ $offset ], $value ) : $value;
				}
			}
		}

		return $word_pattern;
	}