■問題
本家参照.
■解法
ある列群がcandidate superkeyであるかどうかは,以下を判定すれば良い.
・その列群がsuperkeyである
・その列群の真部分集合の全要素がcandidate superkeyでない
superkeyかどうかの判断は,愚直に実装すればOK.
部分集合のビット演算は,「蟻本」の助けを借りました….
public class CandidateKeys{
int n, m;
String[] table;
public int[] getKeys(String[] table){
n=table.length;
m=table[0].length();
this.table=table;
boolean[] candidate=new boolean[1<<m];
int min=-1, max=0;
for(int sup=0;sup<1<<m;sup++){
if(isSuperKey(sup)){
boolean f=true;
for(int sub=(sup-1)⊃sub!=0;sub=(sub-1)&sup){
f&=!candidate[sub];
}
candidate[sup]=f;
if(f){
int bit=Integer.bitCount(sup);
if(min==-1||bit<min){
min=bit;
}
if(bit>max){
max=bit;
}
}
}
// System.out.println(Integer.toString(sup,2)+":"+isSuperKey(sup)+":"+candidate[sup]);
}
if(min==-1){
return new int[0];
}
else{
return new int[]{min, max};
}
}
boolean isSuperKey(int sup){
if(sup==0) return false;
String[] ss=new String[n];
for(int j=0;j<n;j++){
int s=sup;
ss[j]="";
for(int i=m-1;i>=0;i--){
if((s&1)==1){
ss[j]=table[j].charAt(i)+ss[j];
}
s>>=1;
}
}
for(int j=0;j<n;j++){
for(int i=j+1;i<n;i++){
if(ss[i].equals(ss[j])){
return false;
}
}
}
return true;
}
}
0 件のコメント:
コメントを投稿