classSolution{public:stringshortestSuperstring(vector<string>&A){constintn=A.size();// cost[i][j] := cost to append A[j] after A[i]vector<vector<int>>cost(n,vector<int>(n));// GetCost(a, b) := cost to append b after aautogetCost=[](conststring&a,conststring&b){intcost=b.length();constintminLength=min(a.length(),b.length());for(intk=1;k<=minLength;++k)if(a.substr(a.length()-k)==b.substr(0,k))cost=b.length()-k;returncost;};// Pre-calculate cost array to save timefor(inti=0;i<n;++i)for(intj=i+1;j<n;++j){cost[i][j]=getCost(A[i],A[j]);cost[j][i]=getCost(A[j],A[i]);}vector<int>bestPath;intminLength=n*20;// Given by problemdfs(A,cost,{},bestPath,0,0,0,minLength);stringans=A[bestPath[0]];for(intk=1;k<n;++k){constinti=bestPath[k-1];constintj=bestPath[k];ans+=A[j].substr(A[j].length()-cost[i][j]);}returnans;}private:// Used: i-th bit means A[i] is used or notvoiddfs(constvector<string>&A,constvector<vector<int>>&cost,vector<int>&&path,vector<int>&bestPath,intused,intdepth,intcurrLength,int&minLength){if(currLength>=minLength)return;if(depth==A.size()){minLength=currLength;bestPath=path;return;}for(inti=0;i<A.size();++i){if(1<<i&used)continue;path.push_back(i);constintnewLength=depth==0?A[i].length():currLength+cost[path[depth-1]][i];dfs(A,cost,move(path),bestPath,used|1<<i,depth+1,newLength,minLength);path.pop_back();}}};
classSolution{publicStringshortestSuperstring(String[]A){finalintn=A.length;// cost[i][j] := cost to append A[j] after A[i]int[][]cost=newint[n][n];// Pre-calculate cost array to save timefor(inti=0;i<n;++i)for(intj=i+1;j<n;++j){cost[i][j]=getCost(A[i],A[j]);cost[j][i]=getCost(A[j],A[i]);}List<Integer>path=newArrayList<>();List<Integer>bestPath=newArrayList<>();minLength=n*20;// Given by problemdfs(A,cost,path,bestPath,0,0,0);StringBuildersb=newStringBuilder(A[bestPath.get(0)]);for(intk=1;k<n;++k){finalinti=bestPath.get(k-1);finalintj=bestPath.get(k);sb.append(A[j].substring(A[j].length()-cost[i][j]));}returnsb.toString();}privateintminLength;// GetCost(a, b) := cost to append b after aprivateintgetCost(finalStringa,finalStringb){intcost=b.length();finalintminLength=Math.min(a.length(),b.length());for(intk=1;k<=minLength;++k)if(a.substring(a.length()-k).equals(b.substring(0,k)))cost=b.length()-k;returncost;}// Used: i-th bit means A[i] is used or notprivatevoiddfs(String[]A,int[][]cost,List<Integer>path,List<Integer>bestPath,intused,intdepth,intcurrLength){if(currLength>=minLength)return;if(depth==A.length){minLength=currLength;bestPath.clear();for(finalintnode:path){bestPath.add(node);}return;}for(inti=0;i<A.length;++i){if((1<<i&used)>0)continue;path.add(i);finalintnewLength=depth==0?A[i].length():currLength+cost[path.get(depth-1)][i];dfs(A,cost,path,bestPath,used|1<<i,depth+1,newLength);path.remove(path.size()-1);}}}