-
Notifications
You must be signed in to change notification settings - Fork 299
/
Problem_0411_MinimumUniqueWordAbbreviation.java
174 lines (164 loc) · 3.79 KB
/
Problem_0411_MinimumUniqueWordAbbreviation.java
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
package class46;
public class Problem_0411_MinimumUniqueWordAbbreviation {
// 区分出来之后,缩写的长度,最短是多少?
public static int min = Integer.MAX_VALUE;
// 取得缩写的长度最短的时候,决定是什么(fix)
public static int best = 0;
public static int abbrLen(int fix, int len) {
int ans = 0;
int cnt = 0;
for (int i = 0; i < len; i++) {
if ((fix & (1 << i)) != 0) {
ans++;
if (cnt != 0) {
ans += 1;
}
cnt = 0;
} else {
cnt++;
}
}
if (cnt != 0) {
ans += 1;
}
return ans;
}
// 原始的字典,被改了
// target : abc 字典中的词 : bbb -> 101 -> int ->
// fix -> int -> 根本不用值,用状态 -> 每一位保留还是不保留的决定
public static boolean canFix(int[] words, int fix) {
for (int word : words) {
if ((fix & word) == 0) {
return false;
}
}
return true;
}
// 利用位运算加速
public static String minAbbreviation1(String target, String[] dictionary) {
min = Integer.MAX_VALUE;
best = 0;
char[] t = target.toCharArray();
int len = t.length;
int siz = 0;
for (String word : dictionary) {
if (word.length() == len) {
siz++;
}
}
int[] words = new int[siz];
int index = 0;
for (String word : dictionary) {
if (word.length() == len) {
char[] w = word.toCharArray();
int status = 0;
for (int j = 0; j < len; j++) {
if (t[j] != w[j]) {
status |= 1 << j;
}
}
words[index++] = status;
}
}
dfs1(words, len, 0, 0);
StringBuilder builder = new StringBuilder();
int count = 0;
for (int i = 0; i < len; i++) {
if ((best & (1 << i)) != 0) {
if (count > 0) {
builder.append(count);
}
builder.append(t[i]);
count = 0;
} else {
count++;
}
}
if (count > 0) {
builder.append(count);
}
return builder.toString();
}
// 所有字典中的单词现在都变成了int,放在words里
// 0....len-1 位去决定保留还是不保留!当前来到index位
// 之前做出的决定!
public static void dfs1(int[] words, int len, int fix, int index) {
if (!canFix(words, fix)) {
if (index < len) {
dfs1(words, len, fix, index + 1);
dfs1(words, len, fix | (1 << index), index + 1);
}
} else {
// 决定是fix,一共的长度是len,求出缩写是多长?
int ans = abbrLen(fix, len);
if (ans < min) {
min = ans;
best = fix;
}
}
}
// 进一步设计剪枝,注意diff的用法
public static String minAbbreviation2(String target, String[] dictionary) {
min = Integer.MAX_VALUE;
best = 0;
char[] t = target.toCharArray();
int len = t.length;
int siz = 0;
for (String word : dictionary) {
if (word.length() == len) {
siz++;
}
}
int[] words = new int[siz];
int index = 0;
// 用来剪枝
int diff = 0;
for (String word : dictionary) {
if (word.length() == len) {
char[] w = word.toCharArray();
int status = 0;
for (int j = 0; j < len; j++) {
if (t[j] != w[j]) {
status |= 1 << j;
}
}
words[index++] = status;
diff |= status;
}
}
dfs2(words, len, diff, 0, 0);
StringBuilder builder = new StringBuilder();
int count = 0;
for (int i = 0; i < len; i++) {
if ((best & (1 << i)) != 0) {
if (count > 0) {
builder.append(count);
}
builder.append(t[i]);
count = 0;
} else {
count++;
}
}
if (count > 0) {
builder.append(count);
}
return builder.toString();
}
public static void dfs2(int[] words, int len, int diff, int fix, int index) {
if (!canFix(words, fix)) {
if (index < len) {
dfs2(words, len, diff, fix, index + 1);
if ((diff & (1 << index)) != 0) {
dfs2(words, len, diff, fix | (1 << index), index + 1);
}
}
} else {
int ans = abbrLen(fix, len);
if (ans < min) {
min = ans;
best = fix;
}
}
}
}