|
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