public void run() {
      int m = rule.getLength();

      List<Integer> bmBc = preBMBC.get(rule);

      int j;
      byte c, firstCh, secondCh, middleCh, lastCh;

      int secondCharacterLocation = m == 1 ? 0 : 1;

      firstCh = rule.getByte(0);
      secondCh = rule.getByte(secondCharacterLocation);
      middleCh = rule.getByte(m / 2);
      lastCh = rule.getByte(m - 1);

      j = 0;
      while (j <= n - m) {
        c = input.getByte(j + m - 1);
        if (c == lastCh && middleCh == input.getByte(j + m / 2) && firstCh == input.getByte(j)) {
          if (memcmp(rule, input, secondCharacterLocation, j + 1, m - 2)) {
            result.addLocation(j);
          }
        }
        j += bmBc.get(c & 0xFF);
      }
    }
  @Override
  public void search(Input input, Results results, int runNumber, String runId) {
    Result result = new Result(rules, input, this, runNumber, runId);
    result.start();

    int n = input.getLength();

    List<Runnable> runnables = new ArrayList<>();

    rules.forEach(
        rule -> {
          Runnable runnable = new RaitaRunnable(input, result, n, rule);
          runnables.add(runnable);
        });

    executeSearch(runnables);

    result.end();
    results.addResult(result);
  }
    public void run() {
      int i, j, k, s, shift;

      List<Integer> bmBc = preBmBc.get(rule);
      List<Integer> bmGs = preBmGs.get(rule);
      List<Integer> suff = suffixes.get(rule);
      List<Integer> skip = preSkip.get(rule);

      int m = rule.getLength();

      j = 0;
      while (j <= n - m) {
        i = m - 1;
        while (i >= 0) {
          k = skip.get(i);
          s = suff.get(i);
          if (k > 0) {
            if (k > s) {
              if (i + 1 == s) {
                i = -1;
              } else {
                i -= s;
              }
              break;
            } else {
              i -= k;
              if (k < s) {
                break;
              }
            }
          } else {
            if (rule.getByte(i).equals(input.getByte(i + j))) {
              --i;
            } else {
              break;
            }
          }
        }
        if (i < 0) {
          result.addLocation(j);
          skip.set(m - 1, m);
          shift = bmGs.get(0);
        } else {
          skip.set(m - 1, m - 1 - i);
          shift = Math.max(bmGs.get(i), bmBc.get((input.getByte(i + j)) & 0xFF) - m + 1 + i);
        }
        j += shift;
        memcpy(skip, shift, m - shift);
        memset(skip, m - shift, skip.size(), 0);
      }
    }