package com.interview.algorithms.string; /** * Created_By: stefanie * Date: 14-9-22 * Time: 上午11:49 * <p/> * You are given a set of N strings S0, S1, …, SN-1. These strings consist of only lower case characters a..z and have the same length L. * A string H is said to be K-important if there are at least K strings in the given set of N strings appearing at K different positions in H. * These K strings need not to be distinct. * Your task is to find the shortest K-important string. If there are more than one possible solution, your program can output any of them. * * using dynamic programming: * common[i][j]: the common part of strs[i], strs[j], when strs[i] add after strs[j] * opt[k][i]: select K str, and k-th str is strs[i], the min H length * opt[k][i] = min{ opt[k-1][j] + unduplicate(strs[j],strs[i]) } * unduplicate(strs[j],strs[i]) = L - common(strs[i], strs[j]) * sol[k][i]: save the previous of i * * find the min length by search the minimal in opt[K], and backtrace in sol to get the result */ public class C11_29_KImportantString { public static String find(String[] strs, int L, int K){ if(K == 1) return strs[0]; int[][] common = new int[strs.length][strs.length]; for(int i = 0; i < strs.length; i++){ for(int j = 0; j < strs.length; j++){ common[i][j] = common(strs[i], strs[j]); } } int[][] opt = new int[K + 1][strs.length]; int[][] sol = new int[K + 1][strs.length]; for(int i = 0; i < strs.length; i++) { opt[1][i] = L; sol[1][i] = -1; } for(int k = 2; k <= K; k++){ for(int i = 0; i < strs.length; i++){ opt[k][i] = Integer.MAX_VALUE; for(int j = 0; j < strs.length; j++){ int ten = opt[k-1][j] + L - common[i][j]; if(ten < opt[k][i]){ opt[k][i] = ten; sol[k][i] = j; } } } } int min = Integer.MAX_VALUE; int last = -1; for(int i = 0; i < strs.length; i++){ if(opt[K][i] < min){ min = opt[K][i]; last = i; } } StringBuilder builder = new StringBuilder(); int next = last; builder.append(strs[next]); while(K > 1){ last = sol[K--][last]; int c = common[next][last]; builder.insert(0, strs[last].substring(0, L - c)); next = last; } return builder.toString(); } public static int common(String a, String b){ int i = a.length() - 1; for(; i >= 1; i--){ String prefix = a.substring(0, i); if(b.endsWith(prefix)) break; } return i; } }