結果
| 問題 |
No.430 文字列検索
|
| コンテスト | |
| ユーザー |
essence0826
|
| 提出日時 | 2023-09-12 00:11:23 |
| 言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 273 ms / 2,000 ms |
| コード長 | 3,447 bytes |
| コンパイル時間 | 2,833 ms |
| コンパイル使用メモリ | 258,340 KB |
| 実行使用メモリ | 27,776 KB |
| 最終ジャッジ日時 | 2024-11-10 01:07:15 |
| 合計ジャッジ時間 | 4,251 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 4 |
| other | AC * 14 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
#define BE(x) x.begin(), x.end()
using ll = long long;
template<class T> using vec = vector<T>;
class rolling_hash {
private:
using ull = uint64_t;
static const ull max_a = 127ull; // set the max value of sequence to be hashed
static constexpr ull p = (1ull<<61)-1ull;
static const ull p_root = 37ull;
static const int base_n = 2; // number of bases
static ull base[base_n];
static vector<ull> base_pow[base_n];
vector<ull> hash[base_n];
ull mod(ull x) {
ull res = (x>>61) + (x&p);
if (res >= p) res -= p;
return res;
}
ull mul(ull a, ull b) {
constexpr ull mask31 = (1ull<<31)-1ull;
constexpr ull mask30 = (1ull<<30)-1ull;
const ull au = a>>31;
const ull bu = b>>31;
const ull ad = a&mask31;
const ull bd = b&mask31;
const ull mid = au*bd + bu*ad;
const ull midu = mid>>30;
const ull midd = mid&mask30;
return mod(au*bu*2ull + midu+(midd<<31) + ad*bd);
}
ull root_pow(ull ex) {
ull res = 1ull;
ull bin = p_root;
while (ex) {
if (ex&1ull) res = mul(res, bin);
bin = mul(bin, bin);
ex >>= 1;
}
return res;
}
void set_base() {
random_device rd;
mt19937_64 rand(rd());
for (ull &e : base) {
while (!e) {
const ull ex = rand();
if (gcd(ex, p-1ull) != 1ull) continue;
const ull b = root_pow(ex);
if (b <= max_a+1ull) continue;
if (find(base, base+base_n, b) != base+base_n) continue;
e = b;
}
}
}
void set_base_pow(const int n) {
const int prev_size = base_pow[0].size();
for (int i = 0; i < base_n; ++i) {
base_pow[i].resize(n);
base_pow[i][0] = 1ull;
for (int j = prev_size+1; j < n; ++j) {
base_pow[i][j] = mul(base_pow[i][j-1], base[i]);
}
}
}
public:
template<typename T>
rolling_hash(T arr) {
if (!base[0]) set_base();
const int n = arr.size();
if (base_pow[0].size() < (size_t)n) set_base_pow(n+1);
for (int i = 0; i < base_n; ++i) {
hash[i].resize(n+1);
hash[i][0] = 0ull;
for (int j = 0; j < n; ++j) {
hash[i][j+1] = mod(mul(hash[i][j],base[i])+(ull)arr[j]+1ull);
}
}
}
array<ull,base_n> subseq(int l, int r) { // 0-indexed, hankai-kukan
array<ull,base_n> res;
for (int i = 0; i < base_n; ++i) {
ull h = hash[i][r] + p-mul(hash[i][l],base_pow[i][r-l]);
if (h >= p) h -= p;
res[i] = h;
}
return res;
}
using result = array<ull,base_n>;
};
uint64_t rolling_hash::base[];
vector<uint64_t> rolling_hash::base_pow[];
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
string s;
int m;
cin >> s >> m;
int n = s.size();
rolling_hash sh(s);
map<rolling_hash::result,int> p;
for (int i = 1; i <= 10; ++i) {
for (int j = 0; j+i <= n; ++j) {
++p[sh.subseq(j,j+i)];
}
}
int c = 0;
while (m--) {
string t;
cin >> t;
c += p[rolling_hash(t).subseq(0,t.size())];
}
cout << c << '\n';
}
essence0826