- 贴纸拼词
我们有 n 种不同的贴纸。每个贴纸上都有一个小写的英文单词。
您想要拼写出给定的字符串 target ,方法是从收集的贴纸中切割单个字母并重新排列它们。如果你愿意,你可以多次使用每个贴纸,每个贴纸的数量是无限的。
返回你需要拼出 target 的最小贴纸数量。如果任务不可能,则返回 -1 。
注意:在所有的测试用例中,所有的单词都是从 1000 个最常见的美国英语单词中随机选择的,并且 target 被选择为两个随机单词的连接。
public class App
{
public static void main(String[] args) {
String[] strs={"with","example","science"};
System.out.println(new App().minStickers(strs,"thehat"));
}
public int minStickers(String[] stickers, String target) {
HashMap<Character,Integer> targetMap=new HashMap<>();
int n=target.length();
for(int i=0;i<n;i++){
char ch=target.charAt(i);
targetMap.put(ch,targetMap.getOrDefault(ch,0)+1);
}
int total=1;
int[] weight=new int[targetMap.size()];
char[] chars=new char[targetMap.size()];
int count=0;
for(Character ch:targetMap.keySet()){
chars[count]=ch;
weight[count]=targetMap.get(ch)+1;
total*=(weight[count]);
count++;
}
int[][] dp=new int[stickers.length+1][total];
Arrays.fill(dp[0],-1);
dp[0][0]=0;
for(int i=1;i<=stickers.length;i++){
HashMap<Character,Integer> map=new HashMap<>();
for(int k=0;k<stickers[i-1].length();k++){
char ch=stickers[i-1].charAt(k);
map.put(ch,map.getOrDefault(ch,0)+1);
}
for(int j=0;j<total;j++){
if(j==0) {
dp[i][j] = 0;
continue;
}
dp[i][j]=dp[i-1][j];
int[] tmpTarget=resolve(j,weight);
count=0;
while(updateTarget(tmpTarget,chars,map)!=null){
count++;
int tmp=dp[i-1][getIndex(tmpTarget,weight)];
if(dp[i][j]!=-1) {
if (tmp != -1) {
dp[i][j] = Math.min(dp[i][j], tmp + count);
}
}else{
if(tmp!=-1){
dp[i][j]=tmp+count;
}
}
}
}
}
return dp[stickers.length][total-1]==-1?-1:dp[stickers.length][total-1];
}
private int[] updateTarget(int[] target,char[] chars,HashMap<Character,Integer> map){
boolean flag=false;
for(int i=0;i<chars.length;i++){
if(target[i]>0&&map.get(chars[i])!=null){
target[i]-=map.get(chars[i]);
if(target[i]<0){
target[i]=0;
}
flag=true;
}
}
if(flag){
return target;
}else{
return null;
}
}
private int[] resolve(int j,int[] weight){
int[] ans=new int[weight.length];
for(int i=0;i<weight.length;i++){
ans[i]=j%weight[i];
j/=weight[i];
}
return ans;
}
private int getIndex(int[] tmpTarget,int[] weight){
int curWeight=1;
int ans=0;
for(int i=0;i<tmpTarget.length;i++){
ans+=curWeight*tmpTarget[i];
curWeight*=weight[i];
}
return ans;
}
}