|
1 | 1 | package g3301_3400.s3327_check_if_dfs_strings_are_palindromes;
|
2 | 2 |
|
3 |
| -// #Hard #2024_10_21_Time_244_ms_(100.00%)_Space_96.3_MB_(100.00%) |
| 3 | +// #Hard #Array #String #Hash_Table #Tree #Hash_Function #Depth_First_Search |
| 4 | +// #2024_10_22_Time_159_ms_(90.40%)_Space_93.9_MB_(80.80%) |
4 | 5 |
|
5 | 6 | import java.util.ArrayList;
|
| 7 | +import java.util.List; |
6 | 8 |
|
7 | 9 | public class Solution {
|
8 |
| - private StringBuilder dfsString; |
| 10 | + private final List<List<Integer>> e = new ArrayList<>(); |
| 11 | + private final StringBuilder stringBuilder = new StringBuilder(); |
| 12 | + private String s; |
| 13 | + private int now; |
| 14 | + private int n; |
| 15 | + private int[] l; |
| 16 | + private int[] r; |
| 17 | + private int[] p; |
| 18 | + private char[] c; |
9 | 19 |
|
10 |
| - private int[] fillManacher(String s) { |
11 |
| - int n = s.length(); |
12 |
| - s = "$" + s + "@"; |
13 |
| - int[] p = new int[n + 2]; |
14 |
| - int center = 0; |
15 |
| - int right = 0; |
16 |
| - for (int i = 1; i <= n; i++) { |
17 |
| - int mirror = 2 * center - i; |
18 |
| - if (i < right) { |
19 |
| - p[i] = Math.min(right - i, p[mirror]); |
20 |
| - } |
21 |
| - while (s.charAt(i + p[i]) == s.charAt(i - p[i])) { |
22 |
| - p[i]++; |
23 |
| - } |
24 |
| - if (i + p[i] > right) { |
25 |
| - center = i; |
26 |
| - right = i + p[i]; |
27 |
| - } |
| 20 | + private void dfs(int x) { |
| 21 | + l[x] = now + 1; |
| 22 | + for (int v : e.get(x)) { |
| 23 | + dfs(v); |
28 | 24 | }
|
29 |
| - return p; |
| 25 | + stringBuilder.append(s.charAt(x)); |
| 26 | + r[x] = ++now; |
30 | 27 | }
|
31 | 28 |
|
32 |
| - private int[] manacher() { |
33 |
| - StringBuilder temp = new StringBuilder(); |
34 |
| - for (int i = 0; i < dfsString.length(); i++) { |
35 |
| - temp.append("#"); |
36 |
| - temp.append(dfsString.charAt(i)); |
| 29 | + private void manacher() { |
| 30 | + c[0] = '~'; |
| 31 | + c[1] = '#'; |
| 32 | + for (int i = 1; i <= n; ++i) { |
| 33 | + c[2 * i + 1] = '#'; |
| 34 | + c[2 * i] = stringBuilder.charAt(i - 1); |
37 | 35 | }
|
38 |
| - temp.append("#"); |
39 |
| - return fillManacher(String.valueOf(temp)); |
40 |
| - // return Arrays.copyOfRange(arr, 1, arr.length - 1); |
41 |
| - } |
42 |
| - |
43 |
| - private void dfs( |
44 |
| - int node, int parent, ArrayList<ArrayList<Integer>> adj, int[][] range, String s) { |
45 |
| - int start = dfsString.length(); |
46 |
| - |
47 |
| - for (int neigh : adj.get(node)) { |
48 |
| - if (neigh == parent) { |
49 |
| - continue; |
| 36 | + for (int i = 1, mid = 0, r = 0; i <= 2 * n + 1; ++i) { |
| 37 | + if (i <= r) p[i] = Math.min(p[(mid << 1) - i], r - i + 1); |
| 38 | + while (c[i - p[i]] == c[i + p[i]]) ++p[i]; |
| 39 | + if (p[i] + i > r) { |
| 40 | + r = p[i] + i - 1; |
| 41 | + mid = i; |
50 | 42 | }
|
51 |
| - dfs(neigh, node, adj, range, s); |
52 | 43 | }
|
53 |
| - dfsString.append(s.charAt(node)); |
54 |
| - int end = dfsString.length() - 1; |
55 |
| - range[node] = new int[] {start, end}; |
56 | 44 | }
|
57 | 45 |
|
58 | 46 | public boolean[] findAnswer(int[] parent, String s) {
|
59 |
| - dfsString = new StringBuilder(); |
60 |
| - int n = parent.length; |
61 |
| - ArrayList<ArrayList<Integer>> adj = new ArrayList<>(); |
62 |
| - for (int i = 0; i < n; i++) { |
63 |
| - adj.add(new ArrayList<>()); |
| 47 | + n = parent.length; |
| 48 | + this.s = s; |
| 49 | + for (int i = 0; i < n; ++i) { |
| 50 | + e.add(new ArrayList<>()); |
64 | 51 | }
|
65 |
| - for (int i = 0; i < n; i++) { |
66 |
| - if (parent[i] == -1) { |
67 |
| - continue; |
68 |
| - } |
69 |
| - adj.get(parent[i]).add(i); |
| 52 | + for (int i = 1; i < n; ++i) { |
| 53 | + e.get(parent[i]).add(i); |
70 | 54 | }
|
71 |
| - int[][] range = new int[n][2]; |
72 |
| - dfs(0, -1, adj, range, s); |
73 |
| - int[] manacherArr = manacher(); |
| 55 | + l = new int[n]; |
| 56 | + r = new int[n]; |
| 57 | + dfs(0); |
| 58 | + c = new char[2 * n + 10]; |
| 59 | + p = new int[2 * n + 10]; |
| 60 | + manacher(); |
74 | 61 | boolean[] ans = new boolean[n];
|
75 |
| - for (int i = 0; i < n; i++) { |
76 |
| - int[] currRange = range[i]; |
77 |
| - int length = currRange[1] - currRange[0] + 1; |
78 |
| - // +2 because the string has $# in the starting and in the end |
79 |
| - int palindromeStart = 2 * currRange[0] + 2; |
80 |
| - int palindromeEnd = 2 * currRange[1] + 2; |
81 |
| - int center = (palindromeStart + palindromeEnd) / 2; |
82 |
| - // represents the palindrome length having center at center. |
83 |
| - int palindromeLength = manacherArr[center]; |
84 |
| - ans[i] = palindromeLength >= length; |
| 62 | + for (int i = 0; i < n; ++i) { |
| 63 | + int mid = (2 * r[i] - 2 * l[i] + 1) / 2 + 2 * l[i]; |
| 64 | + ans[i] = p[mid] - 1 >= r[i] - l[i] + 1; |
85 | 65 | }
|
86 | 66 | return ans;
|
87 | 67 | }
|
|
0 commit comments