前缀算法能够从一个给定数据空间中找出其前缀特征,即前缀集合。前缀集合具有确定性,能够匹配该前缀集合的数据一定属于该数据空间,否则将一定不属于该数据空间。这样,对一个数据空间的描述既可以利用上下边界来表示,也可以使用该数据空间的前缀特征来表示。
算法1给出了计算给定区间前缀集合算法的伪代码。算法的输入是n位二进制数区间的起始值a1a2...an和结束值b1b2...bn,二进制数的左边是高位,右边是低位,输出是该二进制区间的前缀集合。该算法是一个递归算法,首先,找到二进制区间的起始值和结束值的关键位,即从左到右数第一个不相等的比特位,如果没有找到关键位,则说明该二进制区间的上下边界是重合的,它的前缀特征就是该重合的点;然后,如果起始值的关键位k右边的各位都是0,而且结束值的关键位k右边的各位都是1,则该二进制区间的前缀就是关键位k之前的相似部分;接着,如果前两个条件都不满足,则将起始值和结束值的关键位右边的各位分别作为新的边界输入,递归调用前缀算法去分别计算两个子空间的前缀特征;最后,将子空间的前缀特征与关键位k左边的相似位进行整合,返回二进制区间的前缀集合。
#include <iostream>
#include <vector>
using namespace std;
vector<char *> Search_Prefix(char *begin,char *end)
{
vector<char *> vec;
int len=strlen(begin);
char *tmp;
tmp=new char[len+1];
memset(tmp,'*',len);
tmp[len]='\0';
int k=0;
for (;k<len&&begin[k]==end[k];k++)
{
tmp[k]=begin[k];
}
if (k==len) {
vec.push_back(begin);
return vec;
};
bool bTrue=true;
for (int l=k;l<len;l++)
{
if(!(begin[l]=='0'&&end[l]=='1'))
{
bTrue=false;
}
}
if (bTrue)
{
/* 可取消注释,则11** 返回11* */
// if (k==0)
// {
// vec.push_back("*");
// return vec;
// }
vec.push_back(tmp);
return vec;
}
char *nBegin;
char *nEnd;
int offset=k+1;
int lef=len-offset;
nBegin=new char[lef+1];
nEnd=new char[lef+1];
memset(nBegin,'0',lef);
memset(nEnd,'1',lef);
nBegin[lef]='\0';
nEnd[lef]='\0';
vector<char *> Set_PrefixA=Search_Prefix(begin+offset,nEnd);
vector<char *>Set_PrefixB=Search_Prefix(nBegin,end+offset);
int i=0;
char *Atmp;
for (i=0;i<Set_PrefixA .size();i++)
{
Atmp=new char[len+1];
memset(Atmp,0,len);
Atmp[len]='\0';
strncpy(Atmp,tmp,k);
strcat(Atmp,"0");
strcat(Atmp,Set_PrefixA.at(i));
vec.push_back(Atmp);
}
for (i=0;i<Set_PrefixB.size();i++)
{
Atmp=new char[len+1];
memset(Atmp,0,len);
Atmp[len]='\0';
strncpy(Atmp,tmp,k);
strcat(Atmp,"1");
strcat(Atmp,Set_PrefixB.at(i));
vec.push_back(Atmp);
}
return vec;
}
int main()
{
vector<char *> vec;
vec=Search_Prefix("1101100101","1110100110");
cout<<endl<<"[1101100101,1110100110]"<<endl;
for (int i=0;i<vec.size();i++)
{
cout<<vec.at(i)<<endl;
}
return 0;
}