結果

問題 No.430 文字列検索
ユーザー strangerxxxstrangerxxx
提出日時 2022-11-11 14:37:29
言語 Python3
(3.12.2 + numpy 1.26.4 + scipy 1.12.0)
結果
AC  
実行時間 415 ms / 2,000 ms
コード長 3,370 bytes
コンパイル時間 382 ms
コンパイル使用メモリ 11,316 KB
実行使用メモリ 13,136 KB
最終ジャッジ日時 2023-10-11 11:33:30
合計ジャッジ時間 3,054 ms
ジャッジサーバーID
(参考情報)
judge11 / judge15
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 22 ms
9,540 KB
testcase_01 AC 415 ms
12,528 KB
testcase_02 AC 106 ms
13,044 KB
testcase_03 AC 104 ms
12,968 KB
testcase_04 AC 22 ms
9,432 KB
testcase_05 AC 22 ms
9,408 KB
testcase_06 AC 22 ms
9,572 KB
testcase_07 AC 22 ms
9,516 KB
testcase_08 AC 81 ms
12,060 KB
testcase_09 AC 22 ms
9,560 KB
testcase_10 AC 34 ms
9,728 KB
testcase_11 AC 134 ms
12,764 KB
testcase_12 AC 104 ms
13,136 KB
testcase_13 AC 101 ms
12,916 KB
testcase_14 AC 103 ms
13,020 KB
testcase_15 AC 104 ms
12,912 KB
testcase_16 AC 103 ms
13,048 KB
testcase_17 AC 104 ms
12,944 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

def resolve():
    import sys

    input = sys.stdin.readline
    s = input().rstrip()
    r = RollingHash()
    hashlist = r.head_hash_list(s)
    m = int(input())
    ans = 0
    ls = len(s)
    from collections import defaultdict

    d = defaultdict(set)
    for _ in range(m):
        c = input().rstrip()
        lc = len(c)
        if lc > ls:
            continue
        h = r.get_hash(c)
        d[lc].add(h)
    for k, v in d.items():
        for i in range(ls - k + 1):
            if r.get_hash(hashlist, i, i + k) in v:
                ans += 1
    print(ans)


class RollingHash:
    # verified: https://bit.ly/3X12Gzg
    m = None
    r = None
    rp = {}

    def __init__(self, r: int = None, m=2305843009213693951) -> None:
        if self.m is None:
            self.m = m  # (1 << 61) - 1
        if self.r is None:
            if r is None:
                import random

                r = random.randint(2, self.m - 2)
            self.r = r

    def _powr(self, n: int) -> int:
        if n not in self.rp:
            self.rp[n] = pow(self.r, n, self.m)
        return self.rp[n]

    def hash_list(self, s: str, length: int) -> list:
        n = len(s)
        res = [None] * (n - length + 1)
        x = 0
        for i in s[:length]:
            x *= self.r
            x += ord(i)
            x %= self.m
        res[0] = x
        denom = self._powr(length - 1)
        for i, (j, k) in enumerate(zip(s[length:], s[:-length])):
            x -= ord(k) * denom
            x *= self.r
            x += ord(j)
            x %= self.m
            res[i + 1] = x
        return res

    def gen_hash_list(self, s: str, length: int) -> int:
        x = 0
        for i in s[:length]:
            x *= self.r
            x += ord(i)
            x %= self.m
        yield x
        denom = self._powr(length - 1)
        for i, (j, k) in enumerate(zip(s[length:], s[:-length])):
            x -= ord(k) * denom
            x *= self.r
            x += ord(j)
            x %= self.m
            yield x

    def all_hash_list(self, s: str):
        return [self.hash_list(s, i + 1) for i in range(len(s))]

    def head_hash_list(self, s: str):
        # res[i]:前方i文字のHash
        res = [0] * (len(s) + 1)
        for i, j in enumerate(s):
            res[i + 1] = (res[i] * self.r + ord(j)) % self.m
        return res

    def tail_hash_list(self, s: str):
        # res[i]:後方i文字のHash
        res = [0] * (len(s) + 1)
        x = 1
        for i, j in enumerate(reversed(s)):
            res[i + 1] = (res[i] + x * ord(j)) % self.m
            x = x * self.r
        return res

    def get_hash(self, s_or_head_list, l: int = 0, r: int = None) -> int:
        if type(s_or_head_list) is str:
            if r is None:
                return next(
                    self.gen_hash_list(s_or_head_list[l:], len(s_or_head_list) - l)
                )
            else:
                if l == r:
                    return 0
                g = self.gen_hash_list(s_or_head_list[l:], r - l)
                for _ in range(r - l - 1):
                    next(g)
                return next(g)
        # verified: http://bit.ly/3Uswhjl
        if r is None:
            r = len(s_or_head_list) + 1
        return (s_or_head_list[r] - s_or_head_list[l] * self._powr(r - l)) % self.m


if __name__ == "__main__":
    resolve()
0