1
1
package g3401_3500 .s3435_frequencies_of_shortest_supersequences ;
2
2
3
- // #Hard #2025_01_26_Time_728_(100.00%)_Space_50.28_(100.00%)
3
+ // #Hard #Array #String #Bit_Manipulation #Graph #Enumeration #Topological_Sort
4
+ // #2025_01_27_Time_751_(100.00%)_Space_49.95_(100.00%)
4
5
5
6
import java .util .ArrayList ;
6
7
import java .util .Arrays ;
10
11
import java .util .Map ;
11
12
12
13
public class Solution {
13
- private Map <String , Boolean > buildWordMap (List <String > words ) {
14
- Map <String , Boolean > mp = new HashMap <>();
15
- for (String x : words ) {
16
- mp .put (x , true );
14
+ public List <List <Integer >> supersequences (String [] wordsArray ) {
15
+ List <String > words = new ArrayList <>(Arrays .asList (wordsArray ));
16
+ Collections .sort (words );
17
+ int [] bg = new int [26 ];
18
+ int [] ed = new int [26 ];
19
+ Arrays .fill (bg , -1 );
20
+ Arrays .fill (ed , 0 );
21
+ int [] tans = initializeArrays (words );
22
+ List <String > wtc = buildWtcList (words , tans );
23
+ updateBgEdArrays (wtc , bg , ed );
24
+ List <List <Integer >> ans = new ArrayList <>();
25
+ if (wtc .isEmpty ()) {
26
+ ans .add (convertArrayToList (tans ));
27
+ } else {
28
+ processNonEmptyWtc (wtc , tans , bg , ed , ans );
17
29
}
18
- return mp ;
30
+ return ans ;
19
31
}
20
32
21
- private Map <Character , Boolean > buildCharMap (List <String > words ) {
33
+ private int [] initializeArrays (List <String > words ) {
34
+ Map <String , Boolean > mp = new HashMap <>();
22
35
Map <Character , Boolean > mp2 = new HashMap <>();
23
- for (String x : words ) {
24
- mp2 .put (x .charAt (0 ), true );
25
- mp2 .put (x .charAt (1 ), true );
36
+ for (String word : words ) {
37
+ mp .put (word , true );
38
+ mp2 .put (word .charAt (0 ), true );
39
+ mp2 .put (word .charAt (1 ), true );
26
40
}
27
- return mp2 ;
28
- }
29
-
30
- private int [] initializeAnswerArray (Map <String , Boolean > mp , Map <Character , Boolean > mp2 ) {
31
41
int [] tans = new int [26 ];
32
- Arrays .fill (tans , 0 );
33
42
for (char c = 'a' ; c <= 'z' ; c ++) {
34
43
String aux = "" + c + c ;
35
44
if (mp .containsKey (aux )) {
@@ -41,132 +50,138 @@ private int[] initializeAnswerArray(Map<String, Boolean> mp, Map<Character, Bool
41
50
return tans ;
42
51
}
43
52
44
- private List <String > filterWords (List <String > words , int [] tans ) {
53
+ private List <String > buildWtcList (List <String > words , int [] tans ) {
45
54
List <String > wtc = new ArrayList <>();
46
- for (String x : words ) {
47
- if (tans [x .charAt (0 ) - 'a' ] != 2 && tans [x .charAt (1 ) - 'a' ] != 2 ) {
48
- wtc .add (x );
55
+ for (String word : words ) {
56
+ if (tans [word .charAt (0 ) - 'a' ] != 2 && tans [word .charAt (1 ) - 'a' ] != 2 ) {
57
+ wtc .add (word );
49
58
}
50
59
}
51
60
return wtc ;
52
61
}
53
62
54
- private void updateBoundaries (List <String > wtc , int [] bg , int [] ed ) {
55
- for (int i = 0 ; i < wtc .size (); i ++) {
56
- int l = wtc .get (i ).charAt (0 ) - 'a' ;
57
- if (bg [l ] == -1 ) {
58
- bg [l ] = i ;
59
- }
60
- ed [l ] = i ;
63
+ private void updateBgEdArrays (List <String > wtc , int [] bg , int [] ed ) {
64
+ for (String word : wtc ) {
65
+ int l = word .charAt (0 ) - 'a' ;
66
+ if (bg [l ] == -1 ) bg [l ] = wtc .indexOf (word );
67
+ ed [l ] = wtc .indexOf (word );
61
68
}
62
69
}
63
70
64
- private List <Integer > findMinimalSolutions (List <String > wtc , int [] tans , int [] bg , int [] ed ) {
71
+ private void processNonEmptyWtc (
72
+ List <String > wtc , int [] tans , int [] bg , int [] ed , List <List <Integer >> ans ) {
73
+ List <Integer > ns = buildNsList (tans );
74
+ List <Integer > gm = buildGmList (wtc , tans , bg , ed , ns );
75
+ int minb = findMinBits (gm );
76
+ addMinimalAnswers (gm , minb , ns , tans , ans );
77
+ }
78
+
79
+ private List <Integer > buildNsList (int [] tans ) {
65
80
List <Integer > ns = new ArrayList <>();
66
81
for (int i = 0 ; i < 26 ; i ++) {
67
82
if (tans [i ] == 1 ) {
68
83
ns .add (i );
69
84
}
70
85
}
86
+ return ns ;
87
+ }
88
+
89
+ private List <Integer > buildGmList (
90
+ List <String > wtc , int [] tans , int [] bg , int [] ed , List <Integer > ns ) {
71
91
List <Integer > gm = new ArrayList <>();
72
92
for (int i = 0 ; i < (1 << ns .size ()); i ++) {
73
- if (isValidSolution (i , ns , wtc , tans . clone () , bg , ed )) {
93
+ if (isValidConfiguration (i , wtc , tans , bg , ed , ns )) {
74
94
gm .add (i );
75
95
}
76
96
}
77
97
return gm ;
78
98
}
79
99
80
- private boolean isValidSolution (
81
- int i , List <Integer > ns , List < String > wtc , int [] tans , int [] bg , int [] ed ) {
100
+ private boolean isValidConfiguration (
101
+ int i , List <String > wtc , int [] tans , int [] bg , int [] ed , List < Integer > ns ) {
82
102
int [] indg = new int [26 ];
83
- Arrays .fill (indg , 0 );
103
+ updateTansForConfiguration (i , tans , ns );
104
+ for (String word : wtc ) {
105
+ if (tans [word .charAt (0 ) - 'a' ] != 2 && tans [word .charAt (1 ) - 'a' ] != 2 ) {
106
+ indg [word .charAt (1 ) - 'a' ]++;
107
+ }
108
+ }
109
+ List <Integer > chk = buildChkList (indg , tans );
110
+ processChkList (chk , wtc , tans , bg , ed , indg );
111
+ return Arrays .stream (indg ).max ().orElse (0 ) == 0 ;
112
+ }
113
+
114
+ private void updateTansForConfiguration (int i , int [] tans , List <Integer > ns ) {
84
115
for (int j = 0 ; j < ns .size (); j ++) {
85
116
if ((i & (1 << j )) != 0 ) {
86
117
tans [ns .get (j )] = 2 ;
87
118
} else {
88
119
tans [ns .get (j )] = 1 ;
89
120
}
90
121
}
91
- for (String w : wtc ) {
92
- if (tans [w .charAt (0 ) - 'a' ] != 2 && tans [w .charAt (1 ) - 'a' ] != 2 ) {
93
- indg [w .charAt (1 ) - 'a' ]++;
94
- }
95
- }
96
- return processIndegrees (indg , tans , wtc , bg , ed );
97
122
}
98
123
99
- private boolean processIndegrees ( int [] indg , int [] tans , List <String > wtc , int [] bg , int [] ed ) {
124
+ private List <Integer > buildChkList ( int [] indg , int [] tans ) {
100
125
List <Integer > chk = new ArrayList <>();
101
126
for (int j = 0 ; j < 26 ; j ++) {
102
127
if (indg [j ] == 0 && tans [j ] == 1 ) {
103
128
chk .add (j );
104
129
}
105
130
}
131
+ return chk ;
132
+ }
133
+
134
+ private void processChkList (
135
+ List <Integer > chk , List <String > wtc , int [] tans , int [] bg , int [] ed , int [] indg ) {
106
136
while (!chk .isEmpty ()) {
107
137
int u = chk .remove (chk .size () - 1 );
108
- if (bg [u ] == -1 ) {
109
- continue ;
110
- }
138
+ if (bg [u ] == -1 ) continue ;
139
+
111
140
for (int j = bg [u ]; j <= ed [u ]; j ++) {
112
141
int l = wtc .get (j ).charAt (1 ) - 'a' ;
113
- if (tans [l ] == 2 ) {
114
- continue ;
115
- }
142
+ if (tans [l ] == 2 ) continue ;
116
143
indg [l ]--;
117
144
if (indg [l ] == 0 ) {
118
145
chk .add (l );
119
146
}
120
147
}
121
148
}
122
- return Arrays .stream (indg ).max ().getAsInt () == 0 ;
123
149
}
124
150
125
- public List <List <Integer >> supersequences (String [] wordsArray ) {
126
- List <String > words = new ArrayList <>(Arrays .asList (wordsArray ));
127
- Collections .sort (words );
128
- int [] bg = new int [26 ];
129
- Arrays .fill (bg , -1 );
130
- int [] ed = new int [26 ];
131
- Arrays .fill (ed , 0 );
132
- Map <String , Boolean > mp = buildWordMap (words );
133
- Map <Character , Boolean > mp2 = buildCharMap (words );
134
- int [] tans = initializeAnswerArray (mp , mp2 );
135
- List <String > wtc = filterWords (words , tans );
136
- updateBoundaries (wtc , bg , ed );
137
- List <List <Integer >> ans = new ArrayList <>();
138
- if (wtc .isEmpty ()) {
139
- List <Integer > tansList = new ArrayList <>();
140
- for (int t : tans ) {
141
- tansList .add (t );
142
- }
143
- ans .add (tansList );
144
- return ans ;
151
+ private int findMinBits (List <Integer > gm ) {
152
+ int minb = 20 ;
153
+ for (int x : gm ) {
154
+ minb = Math .min (minb , countSetBits (x ));
145
155
}
146
- List <Integer > gm = findMinimalSolutions (wtc , tans , bg , ed );
147
- int minb = gm .stream ().mapToInt (Integer ::bitCount ).min ().getAsInt ();
148
- List <Integer > ns = new ArrayList <>();
149
- for (int i = 0 ; i < 26 ; i ++) {
150
- if (tans [i ] == 1 ) {
151
- ns .add (i );
156
+ return minb ;
157
+ }
158
+
159
+ private void addMinimalAnswers (
160
+ List <Integer > gm , int minb , List <Integer > ns , int [] tans , List <List <Integer >> ans ) {
161
+ for (int x : gm ) {
162
+ if (countSetBits (x ) == minb ) {
163
+ updateTansForConfiguration (x , tans , ns );
164
+ ans .add (convertArrayToList (tans ));
152
165
}
153
166
}
154
- for (int x : gm ) {
155
- if (Integer .bitCount (x ) == minb ) {
156
- for (int j = 0 ; j < ns .size (); j ++) {
157
- if ((x & (1 << j )) != 0 ) {
158
- tans [ns .get (j )] = 2 ;
159
- } else {
160
- tans [ns .get (j )] = 1 ;
161
- }
162
- }
163
- List <Integer > tansList = new ArrayList <>();
164
- for (int t : tans ) {
165
- tansList .add (t );
166
- }
167
- ans .add (tansList );
167
+ }
168
+
169
+ private int countSetBits (int x ) {
170
+ int count = 0 ;
171
+ while (x > 0 ) {
172
+ if ((x & 1 ) != 0 ) {
173
+ count ++;
168
174
}
175
+ x >>= 1 ;
169
176
}
170
- return ans ;
177
+ return count ;
178
+ }
179
+
180
+ private List <Integer > convertArrayToList (int [] array ) {
181
+ List <Integer > list = new ArrayList <>();
182
+ for (int num : array ) {
183
+ list .add (num );
184
+ }
185
+ return list ;
171
186
}
172
187
}
0 commit comments