You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

175 lines
3.8 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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;
}
}
}
}