manacher.hpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include <vector> | ||
| 4 | #include <cassert> | ||
| 5 | |||
| 6 | /** | ||
| 7 | * manacher(S): return the maximum palindromic substring of S centered at each point | ||
| 8 | * | ||
| 9 | * Input: string (or vector) of length N (no restrictions on character-set) | ||
| 10 | * Output: vector res of length 2*N+1 | ||
| 11 | * For any 0 <= i <= 2*N: | ||
| 12 | * * i % 2 == res[i] % 2 | ||
| 13 | * * the half-open substring S[(i-res[i])/2, (i+res[i])/2) is a palindrome of length res[i] | ||
| 14 | * * For odd palindromes, take odd i, and vice versa | ||
| 15 | */ | ||
| 16 |
1/2✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 24 times.
|
24 | template <typename V> std::vector<int> manacher(const V& S) { |
| 17 | 24 | int N = int(S.size()); | |
| 18 | 24 | std::vector<int> res(2*N+1, 0); | |
| 19 |
2/2✓ Branch 16 → 6 taken 13230408 times.
✓ Branch 16 → 17 taken 24 times.
|
13230432 | for (int i = 1, j = -1, r = 0; i < 2*N; i++, j--) { |
| 20 |
2/2✓ Branch 6 → 7 taken 3793389 times.
✓ Branch 6 → 8 taken 9437019 times.
|
13230408 | if (i > r) { |
| 21 | 3793389 | r = i+1, res[i] = 1; | |
| 22 | } else { | ||
| 23 | 9437019 | res[i] = res[j]; | |
| 24 | } | ||
| 25 |
2/2✓ Branch 9 → 10 taken 13054619 times.
✓ Branch 9 → 15 taken 175789 times.
|
13230408 | if (i+res[i] >= r) { |
| 26 | 13054619 | int b = r>>1, a = i-b; | |
| 27 |
4/4✓ Branch 11 → 12 taken 10876399 times.
✓ Branch 11 → 14 taken 5000047 times.
✓ Branch 12 → 13 taken 2821827 times.
✓ Branch 12 → 14 taken 8054572 times.
|
15876446 | while (a > 0 && b < N && S[a-1] == S[b]) { |
| 28 | 2821827 | a--, b++; | |
| 29 | } | ||
| 30 | 13054619 | res[i] = b-a, j = i, r = b<<1; | |
| 31 | } | ||
| 32 | } | ||
| 33 | 24 | return res; | |
| 34 | } | ||
| 35 | |||
| 36 | /** | ||
| 37 | * manacher_odd(S): return the maximum palindromic substring of S centered at each point | ||
| 38 | * | ||
| 39 | * Input: string (or vector) of length N (no restrictions on character-set) | ||
| 40 | * Output: vector res of length N | ||
| 41 | * For any 0 <= i < N: | ||
| 42 | * * the half-open substring S[i-res[i], i+res[i]] is a palindrome of length 2*res[i]+1 | ||
| 43 | */ | ||
| 44 | ✗ | template <typename V> std::vector<int> manacher_odd(const V& S) { | |
| 45 | ✗ | int N = int(S.size()); | |
| 46 | ✗ | std::vector<int> res(N); | |
| 47 | ✗ | for (int i = 1, j = -1, r = 0; i < N; i++, j--) { | |
| 48 | ✗ | if (i > r) { | |
| 49 | ✗ | r = i, res[i] = 0; | |
| 50 | } else { | ||
| 51 | ✗ | res[i] = res[j]; | |
| 52 | } | ||
| 53 | ✗ | if (i+res[i] >= r) { | |
| 54 | ✗ | int b = r, a = 2*i-r; | |
| 55 | ✗ | while (a-1 >= 0 && b+1 < N && S[a-1] == S[b+1]) { | |
| 56 | ✗ | a--, b++; | |
| 57 | } | ||
| 58 | ✗ | res[i] = b-i, j = i, r = b; | |
| 59 | } | ||
| 60 | } | ||
| 61 | ✗ | return res; | |
| 62 | } | ||
| 63 |