Kyopro Library
 
読み取り中…
検索中…
一致する文字列を見つけられません
rolling_hash.hpp
[詳解]
1#include"../../kyopro_library/template.hpp"
2#include"../../kyopro_library/others/xor128.hpp"
3#include"../../kyopro_library/others/modcal.hpp"
4
5/// @attention 問題の成約に合わせて書き換えること
6constexpr const int HASH_MAX=1000000; ///< 長さの最大値
7constexpr const int HASH_C=256; ///< 文字の範囲
8constexpr const int HASH_PRIME=3; ///< 使う素数の個数
9
10struct Hash {
11
13 static vector<ll> base;
15 static const vector<ll> mod;
16 static bool flag;
17 static array<array<ll,HASH_PRIME>,256> num;
18
20
21 void init() {
22 if(flag) return;
23 flag=true;
24 base=vector<ll>(HASH_PRIME); for(int i=0; i<HASH_PRIME; i++) base[i]=Xor128(3000,mod[i]);
25 inv=vector<vector<ll>>(HASH_PRIME); pow=vector<vector<ll>>(HASH_PRIME);
26 for(int i=0; i<HASH_PRIME; i++) {
27 pow[i]=vector<ll>(HASH_MAX+1); inv[i]=vector<ll>(HASH_MAX+1);
28 pow[i][0]=1; inv[i][HASH_MAX]=ModInv(ModPow<ll>(base[i],HASH_MAX,mod[i]),mod[i]);
29 for(int j=0; j<HASH_MAX; j++) {
30 pow[i][j+1]=(pow[i][j]*base[i])%mod[i];
31 inv[i][HASH_MAX-j-1]=(inv[i][HASH_MAX-j]*base[i])%mod[i];
32 }
33 }
34 for(int i=0; i<HASH_C; i++) for(int j=0; j<HASH_PRIME; j++) num[i][j]=Xor128(1,3000);
35 }
36
37 Hash()=default;
38 Hash(const Hash& other) {
39 if(!flag) init();
40 value=other.value;
41 }
42 Hash(char c) {
43 if(!flag) init();
44 value.fill(0);
45 for(int i=0; i<HASH_PRIME; i++) value[i]=num[c][i];
46 }
47
48 Hash& operator+=(const Hash& other) {
49 for(int i=0; i<HASH_PRIME; i++) value[i]=(value[i]+other.value[i])%mod[i];
50 return *this;
51 }
52 Hash& operator-=(const Hash& other) {
53 for(int i=0; i<HASH_PRIME; i++) value[i]=(value[i]-other.value[i]+mod[i])%mod[i];
54 return *this;
55 }
56 Hash operator+(const Hash& other) const {
57 Hash ret=*this;
58 ret+=other;
59 return ret;
60 }
61 Hash operator-(const Hash& other) const {
62 Hash ret=*this;
63 ret-=other;
64 return ret;
65 }
66 Hash shift(int x) const {
67 Hash ret=*this;
68 if(x<0) for(int i=0; i<HASH_PRIME; i++) (ret.value[i]*=inv[i][-x])%=mod[i];
69 else for(int i=0; i<HASH_PRIME; i++) (ret.value[i]*=pow[i][x])%=mod[i];
70 return ret;
71 }
72 bool operator==(const Hash& other) const {
73 for(int i=0; i<HASH_PRIME; i++) if(value[i]!=other.value[i]) return false;
74 return true;
75 }
76 Hash& operator=(const Hash& other) {
77 for(int i=0; i<HASH_PRIME; i++) value[i]=other.value[i];
78 return *this;
79 }
80};
81
85const vector<ll> Hash::mod={1000000007,1000000009,1000000021,1000000033,1000000087};
86bool Hash::flag=false;
88
89
90///@brief Rolling Hash
92 RollingHash()=default;
94
95 /// @brief 文字列 s の Rolling Hash を構築する
96 RollingHash(const string& s) {
97 int n=s.size();
98 hash.resize(n+1);
99 for(int i=0; i<n; i++) hash[i+1]=hash[i]+Hash(s[i]).shift(i);
100 }
101
102 /// @brief 区間 [l, r) のハッシュ値を取得する
103 Hash get(int l, int r) {
104 Hash ret;
105 ret=hash[r]-hash[l];
106 ret=ret.shift(-l);
107 return ret;
108 }
109};
constexpr const int HASH_C
文字の範囲
constexpr const int HASH_PRIME
使う素数の個数
constexpr const int HASH_MAX
長さの最大値
bool operator==(const Hash &other) const
static bool flag
Hash(const Hash &other)
Hash()=default
Hash operator+(const Hash &other) const
void init()
static vector< ll > base
Type value
Hash operator-(const Hash &other) const
static vector< vector< ll > > pow
Hash(char c)
static vector< vector< ll > > inv
static const vector< ll > mod
Hash & operator+=(const Hash &other)
Hash shift(int x) const
Hash & operator-=(const Hash &other)
Hash & operator=(const Hash &other)
static array< array< ll, HASH_PRIME >, 256 > num
Rolling Hash
RollingHash()=default
Hash get(int l, int r)
区間 [l, r) のハッシュ値を取得する
RollingHash(const string &s)
文字列 s の Rolling Hash を構築する
vector< Hash > hash
ll Xor128(ll l, ll r)
Definition xor128.hpp:18