有关有序HASH树SDK请参考以下网址
http://topic.csdn.net/u/20090820/08/cd6917ee-b22e-412f-8bf1-9afd6770c7e8.html
1.1 前缀匹配应用介绍
目前在信息应用中普遍存在编码的情况,其中前缀方式编码的情况普遍存在,例如:手机电话、固话号码、短信彩信SP号码(短号码)、IP地址、身份证号码、邮政编码、产品编码等等。有序HASH树支持前缀匹配、后缀匹配、以及任意匹配方式,下面主要介绍前缀匹配在电信类软件系统电话号码前缀匹配中的应用,其它行业应用中的前缀匹配类似处理。
1)语音呼叫----号首分析
在语音呼叫过程中通过前缀匹配进行号首分析,分析出被叫号码是否为以下
呼叫类型:本局呼叫、市话呼叫、国内长途(0%)、国际长途、到其他运营商
的呼叫(13%、15%、189%)、增值语音号码(168%),然后进行相应的呼叫。
2)短信彩信----消息路由
(1)短信网关对收到的上下行短信根据号码前缀进行路由,根据前缀路由
到SP、短信中心、异网网关、全国网关等节点。
(2)SP增值应用
SP在短号码的基础上进行扩展为长号码前缀,并在此基础上再次进行匹
配出对应的业务类型。
3)其它应用
根据电话号码前缀进行黑白名单处理、计费处理、归属地处理。
1.2 前缀匹配功能介绍
1、基本前缀(模糊)匹配
如果设置前缀为:
139%
130%
189%
0755%
前缀匹配举例:
号码: 匹配结果:
13912345678 139%
13087654321 130%
18945678902 189%
075587654321 0755%
2、支持多个匹配结果
根据输入号码可以匹配出所有满足条件的前缀规则,且按照精确程度递减排序结果。
如果设置前缀为:
139%
1391%
13912%
139123%
1391234%
前缀匹配举例:
号码: 匹配结果:
13912345678 1391234%、139123%、13912%、1391%、139%
13912356789 139123%、13912%、1391%、139%
13912567890 13912%、1391%、139%
13915678901 1391%、139%
13925678901 139%
3、有序HASH树其它强大功能
插入前缀、删除前缀、遍历前缀等功能,具体参考有序HASH树文档。
1.3 功能实现原理
基于有序HASH树进行关键词的实现原理是把前缀匹配规则插入到有序HASH树
中,然后使用SDK中的反向模糊匹配函数输入文本进行模糊匹配,即可返回满足
条件的前缀规则列表。
1.4 前缀匹配技术特点
1、支持超大规模前缀集合
对32位计算机系统,支持上千万的前缀集合;对64位计算机系统,前缀
的数量没有限制。
1、匹配速度快
基于有序HASH树的前缀匹配的速度与前缀集合中的数量无关,只与前缀的长度有关,是目前速度最快的前缀匹配技术。
2、支持精确匹配和模糊匹配,支持匹配精度递减输出。
1.5 前缀匹配技术指标
1、过滤速度
1)测试环境:
(1)32位windows xp操作系统
(2)1G DDR2内存
(3)CPU:AMD LE1100/1.9GHz
2)前缀集合
1390001%
1390002%
1390003%
。。。。。。。。
1300001%
1300002%
1300003%
1300004%
。。。。。。。。
010%
0755%
。。。。。。。。
168%
160%
12580%
。。。。。。。。。。。。
3)匹配号码
11位手机号码
4)匹配速度
160~210万次/秒
2、最大前缀长度
255个字节
3、容量大
支持上千万前缀规则
1.6 前缀匹配源码实例-1
示例:
功能:根据电话号码在前缀规则集合中匹配出精度最高的前缀。
#include <stdio.h>
#include "HashTree.h"
bool FilterProc(LPSELECTCOND pCond)
{
HANDLE hValue;
hValue = HTreeGetCurrentValue(pCond);
char sKey[32];
HTreeGetCurrentKey(pCond, 0, sKey);
printf("%s %d/r/n", sKey, ((int)(hValue)-1)); // 打印前缀规则和句柄值
return true;
}
int AccessSingle(HANDLE hTree, char* sKey)
{
SELECTCOND pSelectCond;
pSelectCond.hTree = hTree;
pSelectCond.nMethod[0] = RTDB_METHOD_MATCH;
pSelectCond.sIndexValue[0] = sKey;
pSelectCond.bEnableTop = true;
pSelectCond.nTopCount = 1;
pSelectCond.pFilterAPI = FilterProc;
pSelectCond.pFilterPara = NULL;
HTreeSelect(&pSelectCond);
return 0;
}
int main(int nArgc, char* sArgv[])
{
MEMINITINFO MemInitInfo;
MemInitInfo.nSysMaxIdleCount = 1000000;
MemInitInfo.nAppMaxIdleCount = 1000000;
int nRet;
nRet = HTSysInit(&MemInitInfo);
if(nRet != 0)
{
return nRet;
}
HANDLE hTree;
HTREEDESC TreeDesc;
TreeDesc.nColumn = 1;
TreeDesc.nColDataType[0] = CACHE_STRING;
hTree = HTreeCreate(&TreeDesc);// 创建单级树
char* sPrefix[30];
sPrefix[0] = "1390000%";
sPrefix[1] = "1390001%";
sPrefix[2] = "1390002%";
sPrefix[3] = "1390003%";
sPrefix[4] = "1390004%";
sPrefix[5] = "1390005%";
sPrefix[6] = "1390006%";
sPrefix[7] = "1390007%";
sPrefix[8] = "1390008%";
sPrefix[9] = "1390009%";
sPrefix[10] = "1330000%";
sPrefix[11] = "1330001%";
sPrefix[12] = "1330002%";
sPrefix[13] = "1330003%";
sPrefix[14] = "1330004%";
sPrefix[15] = "1330005%";
sPrefix[16] = "1330006%";
sPrefix[17] = "1330007%";
sPrefix[18] = "1330008%";
sPrefix[19] = "1330009%";
sPrefix[20] = "010";
sPrefix[21] = "020%";
sPrefix[22] = "021%";
sPrefix[23] = "0311%";
sPrefix[24] = "0755%";
sPrefix[25] = "0371%";
sPrefix[26] = "0731%";
sPrefix[27] = "025%";
sPrefix[28] = "027%";
sPrefix[29] = "%";
// 以下增加30个前缀规则
int i;
for (i = 0; i < 30; i++)
{
char* sMultiKey[32];
sMultiKey[0] = sPrefix[i];
HTreeAddKey(hTree, sMultiKey, (void*)(i+1));
}
// 匹配出1390009前缀, 对应规则: 1390009%
AccessSingle(hTree, "13900095678");
// 匹配出025前缀, 对应规则: 025%
AccessSingle(hTree, "02512345678");
// 匹配出NULL前缀, 对应规则: %
AccessSingle(hTree, "085612345678");
HTSysDestroy();
return 0;
}
1.7 前缀匹配源码实例-2
示例:
功能:根据电话号码在前缀规则集合中匹配出所有符合条件的前缀,按精度递减输出
#include <stdio.h>
#include "HashTree.h"
typedef struct _PREFIXINFO
{
char sPrefix[32];
char sData[32];
} PREFIXINFO;
typedef PREFIXINFO * LPPREFIXINFO;
int AddPrefixInfo(HANDLE hTree,char* sPrefix, char* sData)
{
LPPREFIXINFO pPrefixInfo;
pPrefixInfo = new PREFIXINFO;
strcpy(pPrefixInfo->sPrefix, sPrefix);
strcpy(pPrefixInfo->sData, sData);
char* sMultiKey[32];
sMultiKey[0] = sPrefix;
return(HTreeAddKey(hTree, sMultiKey, pPrefixInfo));
}
bool FilterProc(LPSELECTCOND pCond)
{
HANDLE hValue;
hValue = HTreeGetCurrentValue(pCond);
LPPREFIXINFO pRetInfo;
pRetInfo = LPPREFIXINFO(hValue);
printf("Prefix: %s/r/n", pRetInfo->sPrefix);
return true;
}
int AccessSingle(HANDLE hTree, char* sKey, bool bTopEnable, int nTopCount)
{
SELECTCOND pSelectCond;
pSelectCond.hTree = hTree;
pSelectCond.nMethod[0] = RTDB_METHOD_MATCH;
pSelectCond.sIndexValue[0] = sKey;
pSelectCond.bEnableTop = bTopEnable;
pSelectCond.nTopCount = nTopCount;
pSelectCond.pFilterAPI = FilterProc;
pSelectCond.pFilterPara = NULL;
HTreeSelect(&pSelectCond);
return 0;
}
int main(int nArgc, char* sArgv[])
{
MEMINITINFO MemInitInfo;
MemInitInfo.nSysMaxIdleCount = 1000000;
MemInitInfo.nAppMaxIdleCount = 1000000;
int nRet;
nRet = HTSysInit(&MemInitInfo);
if(nRet != 0)
{
return nRet;
}
HANDLE hTree;
HTREEDESC TreeDesc;
TreeDesc.nColumn = 1;
TreeDesc.nColDataType[0] = CACHE_STRING;
hTree = HTreeCreate(&TreeDesc);
AddPrefixInfo(hTree, "%", "0");
AddPrefixInfo(hTree, "139%", "139");
AddPrefixInfo(hTree, "1391%", "1391");
AddPrefixInfo(hTree, "13912%", "13912");
AddPrefixInfo(hTree, "139123%", "139123");
AddPrefixInfo(hTree, "1391234%", "1391234");
AddPrefixInfo(hTree, "13912345%", "13912345");
AddPrefixInfo(hTree, "139123456%", "139123456");
AddPrefixInfo(hTree, "1391234567%", "1391234567");
AccessSingle(hTree, "13912345678", false, 0);
// 按精度递减依次输出以下前缀
/*
1391234567%
139123456%
13912345%
1391234%
139123%
13912%
1391%
139%
%
*/
AccessSingle(hTree, "13912345789", false, 0);
// 按精度递减依次输出以下前缀
/*
13912345%
1391234%
139123%
13912%
1391%
139%
%
*/
AccessSingle(hTree, "13912345678", true, 1);
// 输出精度最高的前缀
/*
1391234567%
*/
AccessSingle(hTree, "075587654321", false, 0);
// 缺省的空前缀规则
/*
%
*/
HTSysDestroy();
return 0;
}