您的位置:首页 > 其它

高效全组合算法

2016-02-25 18:00 323 查看
    项目里有个字符串是利用逗号分隔的及部分组合而成的,现在需要将这些被分割部分,最少0个最多全部,替换为星号,生成替换后的这一系列心字符串。例如:a,b,c这个字符串,处理后应该得到这七个结果:a,b,c  *,b,c  *,*,c  *,*,*  a,*,c  a,*,*  a,b,* 。这个问题的本质就是一个全组合的问题,将每个结果中,没被替换的部分看作是一个集合,这7个集合就是原集合的全部子集。
    算法的原理就是利用位运算。假设字符串有n个部分,那就利用一个n位的2进制数来控制每个部分是否被选中。如果某一位为0,则该位的位置对应的字符串部分就被过滤掉,否则就被选中。例如上面的例子中,111代表abc都被选中,结果为a,b,c。001代表只有c被选中,结果为*,*,c 。所以只要遍历1到(2的n次方减1)之间的所有数(我称为标记数)对应的字符结果,就是所有的情况了。0xFFFFFFFF>>>(32
- n)结果既为(2的n次方减1)。
    对于每一种情况,怎么快速检验一位被丢掉,哪一位被选中呢?假设这个标记数是i,想检测它的第j位是0还是1。int设为4字节,32位。首先先将i左移31-j位,就将第j移到了最高位,再将结果右移31位,此时原来的第j位移到了最低位,它左侧的所有位都被填充为原第j位的值。所以此时整个标记数的值只有两种情况0或-1,分别对应第j位卑过滤和被选中的情况。
    项目是Java语言开发的,所以实现了一个Java的全组合算法。代码如下:

public static void main(String[] args) {
String s = "a,b,c";
String str[] = s.split(",");
int nCnt = str.length;
int nBit = (0xFFFFFFFF >>> (32 - nCnt));
for (int i = 1; i <= nBit; i++) {
StringBuffer buffer = new StringBuffer();
for (int j = 0; j < nCnt; j++) {
if ((i << (31 - j)) >> 31 == -1) {
buffer.append(str[j] + ",");
} else {
buffer.append("*,");
}
}
System.out.println(buffer.substring(0, buffer.length() - 1));
}
}

输出结果:

a,*,*
*,b,*
a,b,*
*,*,c
a,*,c
*,b,c
a,b,c

    
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: