結果
| 問題 | No.430 文字列検索 | 
| コンテスト | |
| ユーザー |  | 
| 提出日時 | 2024-05-24 03:36:08 | 
| 言語 | C++23 (gcc 13.3.0 + boost 1.87.0) | 
| 結果 | 
                                AC
                                 
                             | 
| 実行時間 | 479 ms / 2,000 ms | 
| コード長 | 3,070 bytes | 
| コンパイル時間 | 5,460 ms | 
| コンパイル使用メモリ | 278,644 KB | 
| 実行使用メモリ | 5,248 KB | 
| 最終ジャッジ日時 | 2024-11-10 01:11:21 | 
| 合計ジャッジ時間 | 10,207 ms | 
| ジャッジサーバーID (参考情報) | judge4 / judge2 | 
(要ログイン)
| ファイルパターン | 結果 | 
|---|---|
| sample | AC * 4 | 
| other | AC * 14 | 
ソースコード
#define _USE_MATH_DEFINES  // M_PI等のフラグ
#include <bits/stdc++.h>
#define MOD 1000000007
#define COUNTOF(array) (sizeof(array)/sizeof(array[0]))
#define rep(i,n) for (int i = 0; i < (n); ++i)
#define intceil(a,b) ((a+(b-1))/(b))
using namespace std;
using ll = long long;
using pii = pair<int,int>;
using pll = pair<long,long>;
const long long INF = LONG_LONG_MAX - 1001001001001001;
void chmax(ll& x, ll y) { x = max(x,y); }
void chmin(ll& x, ll y) { x = min(x,y); }
string vs = "URDL";  // 上右下左
vector<ll> vy = { -1, 0, 1, 0 };
vector<ll> vx = { 0, 1, 0, -1 };
/***ローリングハッシュ法で文字列検索
 * 計算量はO(N+M)
 ***/
const unsigned long long B = 100000007;  // ハッシュの基数
/***文字列s1はs2に含まれているか?
 * Returns:
 *  含まれている場合、一致箇所の開始位置であるs2のインデックスを返す
 *  含まれていなかった場合、-1を返す
 **/
long long contain(string s1, string s2) {
    long long s1_len = s1.length();
    long long s2_len = s2.length();
    if (s1_len > s2_len) return -1;
    // Bのs1_len乗を計算する
    unsigned long long t = 1;
    for (long long i=0; i<s1_len; i++) t *= B;
    // s1とs2の最初のs1_len文字に関するハッシュ値を計算する
    unsigned long long s1h = 0, s2h = 0;  // ハッシュ値
    for (long long i=0; i<s1_len; i++) s1h = s1h * B + s1[i];
    for (long long i=0; i<s1_len; i++) s2h = s2h * B + s2[i];
    // s2の場所を1つずつ進めながらハッシュ値をチェック
    for (long long i=0; i+s1_len<=s2_len; i++) {
        if (s1h == s2h) return i;  // s2のi文字目からのs1_len文字が一致
        if (i+s1_len < s2_len) s2h = s2h * B + s2[i+s1_len] - s2[i]*t;
    }
    return -1;
 }
/***文字列s1の末尾とs2の先頭を何文字重ねることができるか?
 * Returns:
 *  重なっている文字数を返す。
 *  重なっていなかった場合、0を返す
 ***/
long long overlap(string s1, string s2) {
    long long s1_len = s1.length();
    long long s2_len = s2.length();
    long long ans = 0;
    unsigned long long s1h = 0, s2h = 0;  // ハッシュ値
    unsigned long long t = 1;
    for (long long i=1; i<=min(s1_len, s2_len); i++) {
        s1h = s1h + s1[s1_len-i]*t;  // s1の末尾i文字のハッシュ値
        s2h = s2h * B + s2[i-1];     // s2の先頭i文字のハッシュ値
        if (s1h == s2h) ans = i;
        t *= B;
    }
    return ans;
}
void solve() {
    string S; cin >> S;
    ll M; cin >> M;
    vector<string> C(M);
    for(ll i=0; i<M; i++) {
        cin >> C[i];
    }
    // ローリングハッシュで文字列検索する
    ll ans = 0;
    for(ll i=0; i<M; i++) {
        ll start = 0; // Sの開始位置
        while(1) {
            ll idx = contain(C[i], S.substr(start));
            if (idx == -1) break;
            ans++;
            start += idx + 1;
            if (start >= (ll)S.size()) break;
        }
    }
    cout << ans << endl;
}
int main() {
    solve();
    return 0;
}
            
            
            
        