搜索引擎中长串匹配及聚类算法:后缀树算法
来源:互联网 发布:android启动优化 编辑:程序博客网 时间:2024/05/21 02:50
上个月写了一个后缀树算法,但是生成树的效率极低,这次重新改写,效率接近线性了,c++实现的,下面面是核心算法:
Node *pTmpNode; Edge *pEdge, *pTmpEdge; unsigned int i,edgeNum; unsigned int matchedPos=0;//匹配到的位置 bool bMatched=false; m_pOldNode=NULL; #ifdef Debug #ifdef add_node printf("<<<<<<<<<<<<<< '%s' >>>>>>>>>>>>>>>>\n",subData(start,1).c_str()); #endif #endif //搜索节点是否包含待加入字符 while(!bMatched) { //活动节点:隐含节点为激活节点,或者本身为激活节点 //注意活动节点是非叶节点 //1.匹配整个后缀,即结束节点 //如果是隐含节点 if(m_activeNode.m_bImplicit) { matchedPos=m_activeNode.getImplicitPosition(); if(isDataEqual(start,matchedPos)) { bMatched=true;//退出,因为更短的后缀也肯定是匹配的 } } //显示节点 else { edgeNum=m_activeNode.m_pNode->getChildNum(); for(i=0;i<edgeNum;i++) { matchedPos=m_activeNode.m_pNode->getChildEdge(i)->getStartPos(); if(isDataEqual(start,matchedPos)) { bMatched=true; break; } } } if(bMatched) { //更新激活节点 m_activeNode.increaseImplicitNodeOffset(i);//可能显隐互变? } //最后字符不匹配 else { //2.隐式节点,拆分节点,并添加叶节点 if(m_activeNode.m_bImplicit) { //拆分: pEdge=m_activeNode.getEdge();//上面边 //添加1个节点 pTmpNode=new Node(pEdge);//中间节点 //拆分为2条边 pTmpEdge=new Edge(matchedPos,pEdge->getVirtualEndPos(),pTmpNode,this);//下面边 pEdge->updateEndPosition(matchedPos);//若是叶子节点时,从此摆脱叶子节点 pTmpEdge->setNextNode(pEdge->getNextNode()); pEdge->setNextNode(pTmpNode); pTmpNode->addEdge(pTmpEdge); //隐式节点变显示节点,并作为激活节点(有点牵强?) m_activeNode.setExplicitNode(pTmpNode); //后缀链接 if(m_pOldNode!=NULL) m_pOldNode->setNextSuffixPointer(m_activeNode.m_pNode); m_pOldNode=m_activeNode.m_pNode; #ifdef Debug #ifdef add_node printf("\nsplit:\n %d,%d,%d [%s]\n %d,%d [%s--%s] \n",pEdge->getStartPos(),pEdge->getEndPos(),pTmpEdge->getEndPos(), subData(pEdge->getStartPos(),pTmpEdge->getEndPos()-pEdge->getStartPos()).c_str(),start,start+1, subData(pEdge->getStartPos(),pEdge->getEndPos()-pEdge->getStartPos()).c_str(),subData(start,1).c_str()); #endif #endif } //3.显示节点,仅在显示节点下新增叶子节点 //显示节点下新增叶子节点(含上面隐式变显示的节点) pTmpEdge=new Edge(start,0,m_activeNode.m_pNode,this);//end为0时表示叶子节点 m_activeNode.m_pNode->addEdge(pTmpEdge); #ifdef Debug #ifdef add_node int endPos=0; if(m_activeNode.m_bImplicit) endPos=m_activeNode.getEdge()->getEndPos(); else if(m_activeNode.m_pNode!=m_pRoot) endPos=m_activeNode.m_pNode->getFrontEdge()->getEndPos(); printf("\nnew:\n %d-(%d,%d '%s'--'%s')\n\n",endPos, start,start+1,subData(endPos-1,1).c_str(),subData(pTmpEdge->getStartPos(),pTmpEdge->charSize()).c_str()); #endif #endif //匹配更短的后缀 //判断后缀指针是否存在 if(m_activeNode.m_pNode->hasNextSuffixPointer()) { m_activeNode.setExplicitNode(m_activeNode.m_pNode->getNextSuffix()); } //若不存在则手动搜索下一个更短后缀 else { //4.当前后缀已经为根节点(非隐含),退出 if(m_activeNode.m_pNode==m_pRoot)//!!! bMatched=true; else { CharPosition pos; pTmpNode=m_activeNode.m_pNode; //要查找的更短后缀 string str; /*无论如何此时m_activeNode为显示节点 //(开始就是根节点下的)隐含节点 if(m_activeNode.m_bImplicit)//pTmpEdge==NULL { pTmpEdge=m_activeNode.getEdge(); str=subData(pTmpEdge->getStartPos(),m_activeNode.m_nImplicitNodeOffsetInEdge); }*/ while( (pTmpEdge=pTmpNode->getFrontEdge()) != NULL ) { str.insert(0,subData(pTmpEdge->getStartPos(),pTmpEdge->getEndPos()-pTmpEdge->getStartPos())); pTmpNode=pTmpEdge->getFrontNode(); if(pTmpNode==m_pRoot)//找到根节点下面的边 { break; } } str.erase(0,1); //不连续时会出问题!!! //str=this->subData(pTmpEdge->getStartPos()+1,matchedPos-(pTmpEdge->getStartPos()+1)); if(str.length()==0)//表示没有更短的后缀了,将根节点作为激活节点 { m_activeNode.setExplicitNode(m_pRoot); } else if(search(str,pTmpNode,pos))//必定能找到,查找到结果后,隐式节点返回值pTmpNode为父节点指针 { m_activeNode.m_pNode=pTmpNode; m_activeNode.m_nImplicitNodeEdge=pos.edgeIndex; m_activeNode.m_bImplicit=(pos.charIndex!=0); m_activeNode.m_nImplicitNodeOffsetInEdge=pos.charIndex; } else { printf("################# search error #############\n"); } } } }//end of else }//end of while
- 搜索引擎中长串匹配及聚类算法:后缀树算法
- 搜索引擎中长串匹配及聚类算法:后缀树算法(Java版)
- 基于后缀树的字符串匹配算法
- 蛮力法之串匹配问题---kmp算法中真/后缀作用及next数组计算
- 后缀树(Suffix Tree)的文本匹配算法
- 后缀树(Suffix Tree)的文本匹配算法
- 搜索引擎广告的检索和匹配算法
- 搜索引擎广告的检索和匹配算法
- 字符串匹配算法 最长前缀后缀法
- KMP串匹配算法原理及实现
- 后缀树算法
- 搜索引擎算法系列-BloomFilter算法解析及扩展算法
- Manacher算法,回文串及后缀数组问题
- 搜索引擎算法
- 匹配字符串及KMP算法
- 后缀数组倍增算法代码及解释
- 使用增强型后缀数组(ESA)的文本匹配算法
- 字符串匹配的KMP算法--前缀和后缀的详解
- 四叉树与八叉树
- 道路运输车辆卫星_定位监管系统-车载_终端电压供电技术要求
- 在Ubuntu为Android硬件抽象层(HAL)模块编写JNI方法提供Java访问硬件服务接口
- 转:如何做人生规划?一位前辈给的建议
- 深入学习----Servlet工作原理解析
- 搜索引擎中长串匹配及聚类算法:后缀树算法
- asp中VBScript声明注意
- AT&T 汇编 (AT&T ASM) 参考
- oracle服务简介
- oracle创建自增主键过程与错误分析
- vector<char*>和vector<string>的不同
- 便利的开发工具 CppUnit 快速使用指南
- sqlite入门学习笔记2
- 三个月的总结