多包名取最短包名,或多路径取最短路径,Java解决方案
问题说明:
- 案例
- 现在存在如下的包名:
- com
- com.i2f
- com.i2f.service
- org
- org.cglib
- net
- netscape
- edu.user.service
- edu.admin.model
- edu.user
- 现在要取得这些包名的最短包名:
- com
- org
- net
- netscape
- edu.user
- edu.admin.model
- 下面是java解决方案
- 同样适用于最短公共路径问题
public static List<String> getShortlyPrefixes(String ... pfxes) {
return getShortlyCommonPrefixes(".","\\.",pfxes);
}
public static List<String> getShortlyCommonPrefixes(String separator,String separatorRegex,String ... pfxes) {
Set<String> set=new HashSet<>(36);
for(String item : pfxes){
set.add(item);
}
String[] arr=new String[set.size()];
int p=0;
for(String item : set){
arr[p++]=item;
}
List<String> ret=new ArrayList<>(arr.length);
List<String[]> partsList=new ArrayList<>(arr.length);
Set<Integer> lens=new TreeSet<>();
int maxStrLen=0;
for(String item : arr){
String[] parts=item.split(separatorRegex);
partsList.add(parts);
if(item.length()>maxStrLen){
maxStrLen=item.length();
}
lens.add(parts.length);
}
StringBuilder builder=new StringBuilder(maxStrLen+8);
Set<Integer> excludeIdx = new TreeSet<>();
Iterator<Integer> it=lens.iterator();
while(it.hasNext()){
int len=it.next();
for(int i=0;i<arr.length;i++){
String[] item= partsList.get(i);
if(item.length<len){
continue;
}
if(excludeIdx.contains(i)){
continue;
}
builder.setLength(0);
for(int j=0;j<len;j++){
if(j!=0){
builder.append(separator);
}
builder.append(item[j]);
}
String prefix=builder.toString();
if(!set.contains(prefix)){
continue;
}
for(int j=0;j<arr.length;j++){
if(excludeIdx.contains(j)){
continue;
}
if(arr[j].equals(prefix)){
continue;
}
String pitem=arr[j];
if(pitem.length()>prefix.length()){
if(pitem.startsWith(prefix+separator)){
excludeIdx.add(j);
}
}else{
if(pitem.startsWith(prefix)){
excludeIdx.add(j);
}
}
}
}
}
for(int i=0;i<arr.length;i++){
if(!excludeIdx.contains(i)){
ret.add(arr[i]);
}
}
return ret;
}