常见的字符串算法以及模板,包含了
KMP、Trie、AC自动机,字符串哈希等。
字符串哈希
1 2 3 4 5 6 7 8 9 10 11
| long M = 0x60000005, P = 171; long[] p, h; p[0] = 1; for (int i = 1;i <= n;i++){ h[i] = (h[i-1]*P+(s.charAt(i-1)-'a'+1))%M; p[i] = p[i-1]*P%M; } long get(int l, int r){ return (h[r]-h[l-1]*p[r-l+1]%M+M)%M; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
int rnd(int x, int y) { return uniform_int_distribution<int>(x, y)(rng); }
ll MOD = 1e18 + rnd(0, 1e9), BASE = 233 + rnd(0, 1e3);
struct HashString { vector<__int128_t> P, H;
HashString(string &s) { int n = s.size(); P.resize(n + 1); P[0] = 1; H.resize(n + 1); H[0] = 0; for (int i = 1; i <= n; i++) { P[i] = P[i - 1] * BASE % MOD; H[i] = (H[i - 1] * BASE + s[i - 1]) % MOD; } }
ll query(int l, int r) { return (H[r] - H[l - 1] * P[r - l + 1] % MOD + MOD) % MOD; } };
|
字典树
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| class Node{ Node[] r = new Node[26]; boolean isEnd = false; } static Node root = new Node(); static add(String ss){ Node cur = root; for (int k = 0;k < ss.length();k++){ int x = ss.charAt(k)-'a'; if (cur.r[x] == null) cur.r[x] = new Node(); cur = cur.r[x]; } cur.isEnd = true; } static boolean qurey(String ss){ Node cur = root; for (int k = 0;k < ss.length();k++){ int x = ss.charAt(k)-'a'; if (cur.r[x] == null) return false; cur = cur.r[x]; } return cur.isEnd; }
|
KMP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
for( int i = 2, j = 0; i <=n; i++){ while( j && p[i] != p[j + 1]) j = ne[j]; if( p[i] == p[j + 1]) j ++; ne[i] = j; }
for(int i = 1, j = 0 ; i <= m; i++){ while( j && s[i] != p[ j + 1]) j = ne[j]; if ( s[i] == p [ j + 1 ]) j++; if( j == n){ printf("%d " , i - n ); j = ne[j]; } }
fail = new int[m]; for (int i = 1, j = 0; i < m; ++i) { while (j != 0 && e.charAt(j) != e.charAt(i)) j = fail[j - 1]; if (e.charAt(j) == e.charAt(i)) ++j; fail[i] = j; }
|