結果

問題 No.430 文字列検索
ユーザー ei1333333ei1333333
提出日時 2016-10-02 22:57:43
言語 C++11
(gcc 11.4.0)
結果
AC  
実行時間 73 ms / 2,000 ms
コード長 2,161 bytes
コンパイル時間 1,496 ms
コンパイル使用メモリ 153,688 KB
実行使用メモリ 4,384 KB
最終ジャッジ日時 2023-08-15 17:23:17
合計ジャッジ時間 2,586 ms
ジャッジサーバーID
(参考情報)
judge14 / judge15
このコードへのチャレンジ(β)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
4,376 KB
testcase_01 AC 52 ms
4,380 KB
testcase_02 AC 31 ms
4,380 KB
testcase_03 AC 37 ms
4,380 KB
testcase_04 AC 1 ms
4,380 KB
testcase_05 AC 1 ms
4,380 KB
testcase_06 AC 1 ms
4,376 KB
testcase_07 AC 1 ms
4,380 KB
testcase_08 AC 49 ms
4,380 KB
testcase_09 AC 2 ms
4,380 KB
testcase_10 AC 5 ms
4,384 KB
testcase_11 AC 60 ms
4,380 KB
testcase_12 AC 62 ms
4,376 KB
testcase_13 AC 62 ms
4,376 KB
testcase_14 AC 60 ms
4,384 KB
testcase_15 AC 59 ms
4,376 KB
testcase_16 AC 67 ms
4,380 KB
testcase_17 AC 73 ms
4,380 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>

using namespace std;

typedef unsigned long long hash_type;

struct RollingHash
{
  hash_type base1;
  vector< hash_type > hash1, pow1;

  RollingHash() : base1(29LL)
  {
  }

  void init(const string& s)
  {
    int n = s.size();
    hash1.assign(n + 1, 0);
    pow1.assign(n + 1, 1);
    for(int i = 0; i < n; i++) {
      hash1[i + 1] = (hash1[i] + s[i] - 'A') * base1;
      pow1[i + 1] = pow1[i] * base1;
    }
  }

  hash_type get(int l, int r)
  {
    if(r >= hash1.size()) return (~0);
    return ((hash1[r] - hash1[l] * pow1[r - l]));
  }

};

RollingHash hashed;
int N, M;
string S;

bool compare(const int& a, const int& b)
{
  int low = 0, high = min(N - a, N - b) + 1;
  while(high - low > 1) {
    int mid = (low + high) >> 1;
    if(hashed.get(a, a + mid) == hashed.get(b, b + mid)) low = mid;
    else high = mid;
  }
  if(low == min(N - a, N - b)) return (low == N - a);
  return (S[a + low] < S[b + low]);
}

string T;

bool comp(RollingHash& hashed1, const int& b)
{
  int mm = hashed1.hash1.size() - 1;
  int low = 0, high = min(mm, N - b) + 1;
  while(high - low > 1) {
    int mid = (low + high) >> 1;
    if(hashed1.get(0, mid) == hashed.get(b, b + mid)) low = mid;
    else high = mid;
  }
  if(low == min(mm, N - b)) return (low == mm);
  return (T[low] < S[b + low]);
}

int main()
{
  cin >> S;
  N = S.size();
  hashed.init(S);
  vector< int > idx(S.size());
  iota(idx.begin(), idx.end(), 0);
  sort(idx.begin(), idx.end(), compare);
  int M;
  cin >> M;

  long long ret = 0;
  while(M--) {
    cin >> T;
    RollingHash buff;
    buff.init(T);
    hash_type val = buff.get(0, T.size());
    int low1 = -1, high1 = S.size() - 1;
    while(high1 - low1 > 1) {
      int mid = (low1 + high1) >> 1;
      if(comp(buff, idx[mid])) high1 = mid;
      else low1 = mid;
    }
    if(val != hashed.get(idx[high1], idx[high1] + T.size())) continue;
    int low2 = high1, high2 = S.size();
    while(high2 - low2 > 1) {
      int mid = (low2 + high2) >> 1;
      if(val == hashed.get(idx[mid], idx[mid] + T.size())) low2 = mid;
      else high2 = mid;
    }
    ret += low2 - high1 + 1;
  }
  cout << ret << endl;
}
0