99999久久久久久亚洲,欧美人与禽猛交狂配,高清日韩av在线影院,一个人在线高清免费观看,啦啦啦在线视频免费观看www

熱線電話:13121318867

登錄
首頁(yè)精彩閱讀從Trie樹談到后綴樹之后綴樹的C++簡(jiǎn)單實(shí)現(xiàn)_數(shù)據(jù)分析師
從Trie樹談到后綴樹之后綴樹的C++簡(jiǎn)單實(shí)現(xiàn)_數(shù)據(jù)分析師
2014-11-19
收藏

從Trie樹談到后綴樹之后綴樹的C++簡(jiǎn)單實(shí)現(xiàn)_數(shù)據(jù)分析師

本程序只是簡(jiǎn)單實(shí)現(xiàn)了后綴樹的構(gòu)造,查詢等基本的操作。如果此文能引出讀者更好的suffixtree 的實(shí)現(xiàn),此文的價(jià)值便更甚了。謝謝。

suffix-tree的c++實(shí)現(xiàn)

    完整源碼如下,由于注釋已經(jīng)夠詳細(xì),便不再多說(shuō)什么了:

   

  1. // suffer tree.cpp : 定義控制臺(tái)應(yīng)用程序的入口點(diǎn)。
  2. //copyright@ 2011 July && 匿名
  3. //1、參考了他人的程序,但不知道原作者是誰(shuí)。
  4. //如果你知道,請(qǐng)立馬聯(lián)系我,一定把原作者的大名署上,謝謝。
  5. //2、主函數(shù)沒(méi)有寫全了,讀者視需要自己補(bǔ)上吧。
  6. #include "stdafx.h"
  7. #ifndef __SUFFIXTREE_H
  8. #define __SUFFIXTREE_H
  9. #include 
  10. #include 
  11. #include 
  12. usingnamespacestd;
  13. usingstd::list;
  14. usingstd::vector;
  15. //對(duì)于葉節(jié)點(diǎn),通過(guò)m_nActiveLen和m_nEdgeLabelEndPos可以得到節(jié)點(diǎn)對(duì)應(yīng)的字符串.對(duì)于分支節(jié)點(diǎn),也是如此.
  16. structtagSuffixNode
  17. {
  18. public:
  19. tagSuffixNode* m_tpChild;//子節(jié)點(diǎn),如果為0,說(shuō)明是葉子節(jié)點(diǎn)
  20. tagSuffixNode* m_tpParent;//父節(jié)點(diǎn),根節(jié)點(diǎn)的父節(jié)點(diǎn)為0
  21. tagSuffixNode* m_tpLeftSibling;//左兄弟
  22. tagSuffixNode* m_tpRightSibling;//右兄弟
  23. tagSuffixNode* m_tpMostRightChild;//最右子節(jié)點(diǎn)
  24. tagSuffixNode* m_tpSuffixLink;//指向當(dāng)前節(jié)點(diǎn)表示的子串的最大后綴所對(duì)應(yīng)的分支節(jié)點(diǎn)
  25. intm_nActiveLen;//節(jié)點(diǎn)代表的字符串的長(zhǎng)度.
  26. intm_nEdgeLabelStartPos;//入邊開始字符的下標(biāo).對(duì)于分支節(jié)點(diǎn),只是用來(lái)表示邊對(duì)應(yīng)的字符串是什么,并不表示其在子孫葉節(jié)點(diǎn)表示的串中對(duì)應(yīng)位置的字符在整個(gè)串中的下標(biāo).
  27. intm_nEdgeLabelEndPos;//入邊結(jié)束字符的下標(biāo)
  28. boolm_bIsLeaf;//是否是葉節(jié)點(diǎn)
  29. charm_cIndex;//test
  30. public:
  31. //全部初始化為0
  32. voidinit()
  33. {
  34. m_tpChild = 0;
  35. m_tpParent = 0;
  36. m_tpLeftSibling = 0;
  37. m_tpRightSibling = 0;
  38. m_tpMostRightChild = 0;
  39. m_tpSuffixLink = 0;
  40. m_nEdgeLabelStartPos = 0;
  41. m_nEdgeLabelEndPos = 0;
  42. m_nActiveLen = 0;
  43. m_bIsLeaf =true;
  44. }
  45. };
  46. classCSuffixTree
  47. {
  48. public:
  49. CSuffixTree(char*str);
  50. ~CSuffixTree();
  51. voiddeleteTree();
  52. voidconstruct();
  53. voidreset(char*str);
  54. intsearch(char*str);
  55. tagSuffixNode* getTree();
  56. voidprintTree();
  57. voidtest();
  58. private:
  59. tagSuffixNode* __allocNode();
  60. tagSuffixNode* __findChildBeginWithChar(tagSuffixNode* node,charc);
  61. void__printHelper(tagSuffixNode* node,intlevel);
  62. private:
  63. intm_nActiveLen;
  64. intm_nStrLen;//字符串長(zhǎng)度
  65. tagSuffixNode* m_tpRoot;//根節(jié)點(diǎn)
  66. tagSuffixNode* m_tpActiveNode;//活動(dòng)節(jié)點(diǎn)
  67. char*m_cpInternalStr;//字符串內(nèi)存存儲(chǔ)
  68. list m_tagNodeList;//保存分配的節(jié)點(diǎn)的指針
  69. vector m_tagFromNodeVec;//保存還未確定后綴指針的分支節(jié)點(diǎn)的指針,用于判定suffix link
  70. vector m_tagToNodeVec;//保存所有分支節(jié)點(diǎn)
  71. #ifdef DEBUG
  72. charm_cIndex;
  73. #endif
  74. };
  75. #endif //
  76. //#include "suffixtree.h"
  77. #include 
  78. #include 
  79. #include 
  80. #include 
  81. #include 
  82. usingnamespacestd;
  83. CSuffixTree::CSuffixTree(char*str)
  84. :m_nActiveLen(0),
  85. m_tpRoot(0),
  86. m_tpActiveNode(0)
  87. {
  88. m_nStrLen = strlen(str) + 1;
  89. m_cpInternalStr =newchar[m_nStrLen+1];
  90. sprintf(m_cpInternalStr,"%s#", str);
  91. #ifdef DEBUG
  92. m_cIndex ='A';
  93. #endif
  94. }
  95. CSuffixTree::~CSuffixTree()
  96. {
  97. deleteTree();
  98. delete[] m_cpInternalStr;
  99. }
  100. voidCSuffixTree::deleteTree()
  101. {
  102. list::iterator iter = m_tagNodeList.begin();
  103. for(; iter != m_tagNodeList.end(); ++iter)
  104. {
  105. delete*iter;
  106. }
  107. m_tagNodeList.clear();
  108. }
  109. voidCSuffixTree::reset(char*str)
  110. {
  111. deleteTree();
  112. inttmp = strlen(str);
  113. if(tmp+1 > m_nStrLen)
  114. {
  115. m_nStrLen = tmp+1;
  116. delete[] m_cpInternalStr;
  117. m_cpInternalStr =newchar[m_nStrLen+1];
  118. }
  119. else
  120. {
  121. m_nStrLen = tmp+1;
  122. }
  123. sprintf(m_cpInternalStr,"%s#", str);
  124. m_nActiveLen = 0;
  125. m_nStrLen = 0;
  126. m_tpActiveNode = 0;
  127. m_tpRoot = 0;
  128. m_tagFromNodeVec.clear();
  129. //reconstruct tree for new string
  130. construct();
  131. }
  132. //suffixTree之構(gòu)造
  133. voidCSuffixTree::construct()
  134. {
  135. m_tpRoot = __allocNode();
  136. if(m_tpRoot == 0)
  137. {
  138. #ifdef DEBUG
  139. printf("__allocNode error!\n");
  140. #endif
  141. return;
  142. }
  143. m_nActiveLen = 0;
  144. m_tpRoot->m_nActiveLen = 0;
  145. //initial active node
  146. m_tpActiveNode = m_tpRoot;
  147. m_tagToNodeVec.push_back(m_tpRoot);
  148. for(inti = 0; i
  149. {
  150. #ifdef DEBUG
  151. printf("\ninsert %s\n", &(m_cpInternalStr[i]));
  152. printf("active node:[%c]\n", m_tpActiveNode->m_cIndex);
  153. #endif
  154. //判斷是否有后繼節(jié)點(diǎn)
  155. if(m_tpActiveNode->m_tpSuffixLink != 0)
  156. {
  157. m_tpActiveNode = m_tpActiveNode->m_tpSuffixLink;
  158. m_nActiveLen--;
  159. }
  160. intpos = i;
  161. #ifdef DEBUG
  162. printf("new active node:[%c]\n", m_tpActiveNode->m_cIndex);
  163. printf("pos:%d\n", pos);
  164. printf("active length:%d\n", m_nActiveLen);
  165. #endif
  166. while(true)
  167. {
  168. //查找以當(dāng)前后綴串的開始字符開始的子節(jié)點(diǎn)
  169. tagSuffixNode* node = __findChildBeginWithChar(m_tpActiveNode, m_cpInternalStr[i+m_nActiveLen]);
  170. //未找到以suffix[i]的開始字符開頭的節(jié)點(diǎn)
  171. if(node == 0)
  172. {
  173. #ifdef DEBUG
  174. printf("__findChildBeginWithChar null\n");
  175. #endif
  176. tagSuffixNode* child = __allocNode();
  177. //設(shè)置開始、結(jié)束位置的下標(biāo)
  178. child->m_nEdgeLabelStartPos = pos;
  179. child->m_nEdgeLabelEndPos = m_nStrLen-1;
  180. //設(shè)置葉節(jié)點(diǎn)代表的后綴串的長(zhǎng)度
  181. child->m_nActiveLen = m_nStrLen - i;
  182. //設(shè)置父節(jié)點(diǎn)
  183. child->m_tpParent = m_tpActiveNode;
  184. if( m_tpActiveNode->m_tpChild == 0)
  185. {
  186. m_tpActiveNode->m_tpChild = child;
  187. m_tpActiveNode->m_tpMostRightChild = child;
  188. }
  189. else
  190. {
  191. m_tpActiveNode->m_tpMostRightChild->m_tpRightSibling = child;
  192. child->m_tpLeftSibling = m_tpActiveNode->m_tpMostRightChild;
  193. m_tpActiveNode->m_tpMostRightChild = child;
  194. }
  195. break;
  196. }
  197. else
  198. {
  199. #ifdef DEBUG
  200. printf("__findChildBeginWithChar ok\n");
  201. printf("node start:%d\n", node->m_nEdgeLabelStartPos);
  202. printf("node end:%d\n", node->m_nEdgeLabelEndPos);
  203. printf("node index:%c\n", node->m_cIndex);
  204. #endif
  205. //TODO
  206. //確定 m_nMinDistance
  207. intedgeStart = node->m_nEdgeLabelStartPos;
  208. intstrStart = i + m_nActiveLen;
  209. boolsplit =false;
  210. for(; edgeStart<=node->m_nEdgeLabelEndPos; edgeStart++, strStart++)
  211. {
  212. if( m_cpInternalStr[edgeStart] != m_cpInternalStr[strStart])
  213. {
  214. split =true;
  215. break;
  216. }
  217. }
  218. if(!split)
  219. {
  220. m_tpActiveNode = node;
  221. m_nActiveLen += node->m_nEdgeLabelEndPos - node->m_nEdgeLabelStartPos + 1;
  222. pos += node->m_nEdgeLabelEndPos - node->m_nEdgeLabelStartPos + 1;
  223. continue;
  224. }
  225. else
  226. {
  227. tagSuffixNode* parent = node->m_tpParent;
  228. //new branch node
  229. tagSuffixNode* branch = __allocNode();
  230. branch->m_bIsLeaf =false;
  231. branch->m_nEdgeLabelStartPos = node->m_nEdgeLabelStartPos;
  232. branch->m_nEdgeLabelEndPos = edgeStart-1;
  233. branch->m_nActiveLen = parent->m_nActiveLen + (branch->m_nEdgeLabelEndPos - branch->m_nEdgeLabelStartPos + 1);
  234. //original node
  235. node->m_nEdgeLabelStartPos = edgeStart;
  236. tagSuffixNode* info = __allocNode();
  237. info->m_nEdgeLabelStartPos = strStart;
  238. info->m_nEdgeLabelEndPos = m_nStrLen - 1;
  239. info->m_nActiveLen = branch->m_nActiveLen + (info->m_nEdgeLabelEndPos - info->m_nEdgeLabelStartPos + 1);
  240. branch->m_tpParent = parent;
  241. branch->m_tpRightSibling = parent->m_tpChild;
  242. parent->m_tpChild->m_tpLeftSibling = branch;
  243. parent->m_tpChild = branch;
  244. node->m_tpLeftSibling->m_tpRightSibling = node->m_tpRightSibling;
  245. if( node->m_tpRightSibling != 0)
  246. {
  247. node->m_tpRightSibling->m_tpLeftSibling = node->m_tpLeftSibling;
  248. }
  249. else
  250. {
  251. parent->m_tpMostRightChild = node->m_tpLeftSibling;
  252. }
  253. branch->m_tpChild = info;
  254. branch->m_tpMostRightChild = node;
  255. info->m_tpRightSibling = node;
  256. info->m_tpParent = branch;
  257. node->m_tpParent = branch;
  258. node->m_tpLeftSibling = info;
  259. node->m_tpRightSibling = 0;
  260. //設(shè)置節(jié)點(diǎn)的suffix link
  261. boolsetSuffix =false;
  262. vector::iterator iter = m_tagToNodeVec.begin();
  263. for(; iter != m_tagToNodeVec.end(); ++iter)
  264. {
  265. tagSuffixNode* tmp = *iter;
  266. if( strncmp( &(m_cpInternalStr[branch->m_nEdgeLabelEndPos - branch->m_nActiveLen + 2]), &(m_cpInternalStr[tmp->m_nEdgeLabelEndPos - tmp->m_nActiveLen + 1]), branch->m_nActiveLen - 1) == 0)
  267. {
  268. branch->m_tpSuffixLink = tmp;
  269. setSuffix =true;
  270. break;
  271. #ifdef DEBUG
  272. printf("branch[%c] suffix_link is branch[%c]\n", tmp->m_cIndex, branch->m_cIndex);
  273. #endif
  274. }
  275. }
  276. m_tagToNodeVec.push_back(branch);
  277. vector::iterator iter2 = m_tagFromNodeVec.begin();
  278. for(; iter2 != m_tagFromNodeVec.end(); ++iter2)
  279. {
  280. tagSuffixNode* tmp = *iter2;
  281. //找到后綴節(jié)點(diǎn),結(jié)束循環(huán)
  282. if( strncmp( &(m_cpInternalStr[tmp->m_nEdgeLabelEndPos - tmp->m_nActiveLen + 2]), &(m_cpInternalStr[branch->m_nEdgeLabelEndPos - branch->m_nActiveLen + 1]), tmp->m_nActiveLen - 1) == 0)
  283. {
  284. tmp->m_tpSuffixLink = branch;
  285. m_tagFromNodeVec.erase(iter2);
  286. #ifdef DEBUG
  287. printf("branch[%c] suffix_link is branch[%c]\n", tmp->m_cIndex, branch->m_cIndex);
  288. #endif
  289. break;
  290. }
  291. }
  292. if( !setSuffix )
  293. {
  294. m_tagFromNodeVec.push_back(branch);
  295. }
  296. //已經(jīng)將新的后綴字符串插入到樹中,這時(shí)可以結(jié)束while了。
  297. break;
  298. }
  299. }
  300. }
  301. //test
  302. #ifdef DEBUG
  303. printf("print\n");
  304. printTree();
  305. #endif
  306. }
  307. }
  308. //查詢
  309. intCSuffixTree::search(char*str)
  310. {
  311. if(str == 0)
  312. return-1;
  313. //TODO
  314. //添加處理過(guò)程
  315. intlen = strlen(str);
  316. tagSuffixNode* node = 0;
  317. tagSuffixNode* cur = m_tpRoot;
  318. for(inti=0; i
  319. {
  320. node = __findChildBeginWithChar(cur, str[i]);
  321. if(node == 0)
  322. {
  323. break;
  324. }
  325. else
  326. {
  327. intedgeLen = node->m_nEdgeLabelEndPos - node->m_nEdgeLabelStartPos + 1;
  328. intremain = len - i;
  329. if( remain <= edgeLen )
  330. {
  331. if( strncmp(&(str[i]), &(m_cpInternalStr[node->m_nEdgeLabelStartPos]), remain) != 0)
  332. {
  333. return-1;
  334. }
  335. else
  336. {
  337. returnnode->m_nEdgeLabelEndPos - node->m_nActiveLen + 1;
  338. }
  339. }
  340. else
  341. {
  342. if( strncmp(&(str[i]), &(m_cpInternalStr[node->m_nEdgeLabelStartPos]), edgeLen) != 0)
  343. {
  344. return-1;
  345. }
  346. else
  347. {
  348. i += edgeLen;
  349. cur = node;
  350. }
  351. }
  352. }
  353. }
  354. return-1;
  355. }
  356. tagSuffixNode* CSuffixTree::__allocNode()
  357. {
  358. tagSuffixNode* node =newtagSuffixNode;
  359. m_tagNodeList.push_back(node);
  360. node->init();
  361. #ifdef DEBUG
  362. node->m_cIndex = m_cIndex;
  363. m_cIndex++;
  364. #endif
  365. returnnode;
  366. }
  367. tagSuffixNode* CSuffixTree::__findChildBeginWithChar(tagSuffixNode* node,charc)
  368. {
  369. assert(node != 0);
  370. tagSuffixNode* child = node->m_tpChild;
  371. while(child != 0)
  372. {
  373. if( m_cpInternalStr[child->m_nEdgeLabelStartPos] == c)
  374. returnchild;
  375. child = child->m_tpRightSibling;
  376. }
  377. return0;
  378. }
  379. voidCSuffixTree::test()
  380. {
  381. //printf("%s\n", m_cpInternalStr);
  382. printTree();
  383. }
  384. voidCSuffixTree::printTree()
  385. {
  386. #ifdef DEBUG
  387. printf("[A]\n");
  388. #endif
  389. __printHelper(m_tpRoot, 0);
  390. }
  391. voidCSuffixTree::__printHelper(tagSuffixNode* node,intlevel)
  392. {
  393. intstart = node->m_nEdgeLabelStartPos;
  394. intend = node->m_nEdgeLabelEndPos;
  395. tagSuffixNode* child = node->m_tpChild;
  396. if( level > 0 )
  397. {
  398. for(inti=0; i
  399. {
  400. printf(" |");
  401. }
  402. printf(" + ");
  403. for(intj = start; j <= end; j++)
  404. {
  405. printf("%c", m_cpInternalStr[j]);
  406. }
  407. #ifdef DEBUG
  408. printf("[%c]", node->m_cIndex);
  409. //         printf("[%d:%d:%d]", node->m_nEdgeLabelStartPos, node->m_nEdgeLabelEndPos, node->m_nActiveLen);
  410. #endif
  411. printf("\n");
  412. }
  413. while( child != 0 )
  414. {
  415. __printHelper(child, level+1);
  416. child = child->m_tpRightSibling;
  417. }
  418. }
  419. intmain()
  420. {
  421. cout<<"hello suffixtree"<
  422. system("pause");
  423. return0;
  424. }

   

    運(yùn)行結(jié)果如下:1024x551

Shlomo Yona的實(shí)現(xiàn)

    下面是國(guó)外一牛人Shlomo Yona寫的實(shí)現(xiàn)(摘取了部分非完整代碼):

   

  1. /******************************************************************************
  2. Suffix Tree Version 2.1
  3. AUTHORS
  4. Dotan Tsadok
  5. Instructor: Mr. Shlomo Yona, University of Haifa, Israel. December 2002.
  6. Current maintainer: Shlomo Yona 
  7. COPYRIGHT
  8. Copyright 2002-2003 Shlomo Yona
  9. LICENSE
  10. This library is free software; you can redistribute it and/or modify it
  11. under the same terms as Perl itself.
  12. DESCRIPTION OF THIS FILE:
  13. This is the implementation file suffix_tree.c implementing the header file
  14. suffix_tree.h.
  15. This code is an Open Source implementation of Ukkonen's algorithm for
  16. constructing a suffix tree over a string in time and space complexity
  17. O(length of the string). The code is written under strict ANSI C.
  18. For a complete understanding of the code see Ukkonen's algorithm and the
  19. readme.txt file.
  20. The general pseudo code is:
  21. n = length of the string.
  22. ST_CreateTree:
  23. Calls n times to SPA (Single Phase Algorithm). SPA:
  24. Increase the variable e (virtual end of all leaves).
  25. Calls SEA (Single Extension Algorithm) starting with the first extension that
  26. does not already exist in the tree and ending at the first extension that
  27. already exists. SEA :
  28. Follow suffix link.
  29. Check if current suffix exists in the tree.
  30. If it does not - apply rule 2 and then create a new suffix link.
  31. apply_rule_2:
  32. Create a new leaf and maybe a new internal node as well.
  33. create_node:
  34. Create a new node or a leaf.
  35. For implementation interpretations see Basic Ideas paragraph in the Developement
  36. section of the readme.txt file.
  37. An example of the implementations of a node and its sons using linked lists
  38. instead of arrays:
  39. (1)
  40. |
  41. |
  42. |
  43. (2)--(3)--(4)--(5)
  44. (2) is the only son of (1) (call it the first son). Other sons of (1) are
  45. connected using a linked lists starting from (2) and going to the right. (3) is
  46. the right sibling of (2) (and (2) is the left sibling of (3)), (4) is the right
  47. sibling of (3), etc.
  48. The father field of all (2), (3), (4) and (5) points to (1), but the son field
  49. of (1) points only to (2).
  50. *******************************************************************************/
  51. #include "stdlib.h"
  52. #include "stdio.h"
  53. #include "string.h"
  54. #include "suffix_tree.h"
  55. /* See function body */
  56. voidST_PrintTree(SUFFIX_TREE* tree);
  57. /* See function body */
  58. voidST_PrintFullNode(SUFFIX_TREE* tree, NODE* node);
  59. /* Used in function trace_string for skipping (Ukkonen's Skip Trick). */
  60. typedefenumSKIP_TYPE     {skip, no_skip}                 SKIP_TYPE;
  61. /* Used in function apply_rule_2 - two types of rule 2 - see function for more
  62. details.*/
  63. typedefenumRULE_2_TYPE   {new_son, split}                RULE_2_TYPE;
  64. /* Signals whether last matching position is the last one of the current edge */
  65. typedefenumLAST_POS_TYPE {last_char_in_edge, other_char} LAST_POS_TYPE;
  66. /* Used for statistic measures of speed. */
  67. DBL_WORD counter;
  68. /* Used for statistic measures of space. */
  69. DBL_WORD heap;
  70. /* Used to mark the node that has no suffix link yet. By Ukkonen, it will have
  71. one by the end of the current phase. */
  72. NODE*    suffixless;
  73. typedefstructSUFFIXTREEPATH
  74. {
  75. DBL_WORD   begin;
  76. DBL_WORD   end;
  77. } PATH;
  78. typedefstructSUFFIXTREEPOS
  79. {
  80. NODE*      node;
  81. DBL_WORD   edge_pos;
  82. }POS;
  83. /******************************************************************************/
  84. /*
  85. Define STATISTICS in order to view measures of speed and space while
  86. constructing and searching the suffix tree. Measures will be printed on the
  87. screen.
  88. */
  89. /* #define STATISTICS */
  90. /*
  91. Define DEBUG in order to view debug printouts to the screen while
  92. constructing and searching the suffix tree.
  93. */
  94. /* #define DEBUG */
  95. /******************************************************************************/
  96. /*
  97. create_node :
  98. Creates a node with the given init field-values.
  99. Input : The father of the node, the starting and ending indices
  100. of the incloming edge to that node,
  101. the path starting position of the node.
  102. Output: A pointer to that node.
  103. */
  104. NODE* create_node(NODE* father, DBL_WORD start, DBL_WORD end, DBL_WORD position)
  105. {
  106. /*Allocate a node.*/
  107. NODE* node   = (NODE*)malloc(sizeof(NODE));
  108. if(node == 0)
  109. {
  110. printf("\nOut of memory.\n");
  111. exit(0);
  112. }
  113. #ifdef STATISTICS
  114. heap+=sizeof(NODE);
  115. #endif
  116. /* Initialize node fields. For detailed description of the fields see
  117. suffix_tree.h */
  118. node->sons             = 0;
  119. node->right_sibling    = 0;
  120. node->left_sibling     = 0;
  121. node->suffix_link      = 0;
  122. node->father           = father;
  123. node->path_position    = position;
  124. node->edge_label_start = start;
  125. node->edge_label_end   = end;
  126. returnnode;
  127. }
  128. /******************************************************************************/
  129. /*
  130. find_son :
  131. Finds son of node that starts with a certain character.
  132. Input : the tree, the node to start searching from and the character to be
  133. searched in the sons.
  134. Output: A pointer to the found son, 0 if no such son.
  135. */
  136. NODE* find_son(SUFFIX_TREE* tree, NODE* node,charcharacter)
  137. {
  138. /* Point to the first son. */
  139. node = node->sons;
  140. /* scan all sons (all right siblings of the first son) for their first
  141. character (it has to match the character given as input to this function. */
  142. while(node != 0 && tree->tree_string[node->edge_label_start] != character)
  143. {
  144. #ifdef STATISTICS
  145. counter++;
  146. #endif
  147. node = node->right_sibling;
  148. }
  149. returnnode;
  150. }
  151. /******************************************************************************/
  152. /*
  153. get_node_label_end :
  154. Returns the end index of the incoming edge to that node. This function is
  155. needed because for leaves the end index is not relevant, instead we must look
  156. at the variable "e" (the global virtual end of all leaves). Never refer
  157. directly to a leaf's end-index.
  158. Input : the tree, the node its end index we need.
  159. Output: The end index of that node (meaning the end index of the node's
  160. incoming edge).
  161. */
  162. DBL_WORD get_node_label_end(SUFFIX_TREE* tree, NODE* node)
  163. {
  164. /* If it's a leaf - return e */
  165. if(node->sons == 0)
  166. returntree->e;
  167. /* If it's not a leaf - return its real end */
  168. returnnode->edge_label_end;
  169. }
  170. /******************************************************************************/
  171. /*
  172. get_node_label_length :
  173. Returns the length of the incoming edge to that node. Uses get_node_label_end
  174. (see above).
  175. Input : The tree and the node its length we need.
  176. Output: the length of that node.
  177. */
  178. DBL_WORD get_node_label_length(SUFFIX_TREE* tree, NODE* node)
  179. {
  180. /* Calculate and return the lentgh of the node */
  181. returnget_node_label_end(tree, node) - node->edge_label_start + 1;
  182. }
  183. /******************************************************************************/
  184. /*
  185. is_last_char_in_edge :
  186. Returns 1 if edge_pos is the last position in node's incoming edge.
  187. Input : The tree, the node to be checked and the position in its incoming
  188. edge.
  189. Output: the length of that node.
  190. */
  191. charis_last_char_in_edge(SUFFIX_TREE* tree, NODE* node, DBL_WORD edge_pos)
  192. {
  193. if(edge_pos == get_node_label_length(tree,node)-1)
  194. return1;
  195. return0;
  196. }
  197. /******************************************************************************/
  198. /*
  199. connect_siblings :
  200. Connect right_sib as the right sibling of left_sib and vice versa.
  201. Input : The two nodes to be connected.
  202. Output: None.
  203. */
  204. voidconnect_siblings(NODE* left_sib, NODE* right_sib)
  205. {
  206. /* Connect the right node as the right sibling of the left node */
  207. if(left_sib != 0)
  208. left_sib->right_sibling = right_sib;
  209. /* Connect the left node as the left sibling of the right node */
  210. if(right_sib != 0)
  211. right_sib->left_sibling = left_sib;
  212. }
  213. /******************************************************************************/
  214. /*
  215. apply_extension_rule_2 :
  216. Apply "extension rule 2" in 2 cases:
  217. 1. A new son (leaf 4) is added to a node that already has sons:
  218. (1)        (1)
  219. /   \     ->   / | \
  220. (2)  (3)      (2)(3)(4)
  221. 2. An edge is split and a new leaf (2) and an internal node (3) are added:
  222. |       |
  223. |      (3)
  224. |     ->   / \
  225. (1)       (1) (2)
  226. Input : See parameters.
  227. Output: A pointer to the newly created leaf (new_son case) or internal node
  228. (split case).
  229. */
  230. NODE* apply_extension_rule_2(
  231. /* Node 1 (see drawings) */
  232. NODE*           node,
  233. /* Start index of node 2's incoming edge */
  234. DBL_WORD        edge_label_begin,
  235. /* End index of node 2's incoming edge */
  236. DBL_WORD        edge_label_end,
  237. /* Path start index of node 2 */
  238. DBL_WORD        path_pos,
  239. /* Position in node 1's incoming edge where split is to be
  240. performed */
  241. DBL_WORD        edge_pos,
  242. /* Can be 'new_son' or 'split' */
  243. RULE_2_TYPE     type)
  244. {
  245. NODE *new_leaf,
  246. *new_internal,
  247. *son;
  248. /*-------new_son-------*/
  249. if(type == new_son)
  250. {
  251. #ifdef DEBUG
  252. printf("rule 2: new leaf (%lu,%lu)\n",edge_label_begin,edge_label_end);
  253. #endif
  254. /* Create a new leaf (4) with the characters of the extension */
  255. new_leaf = create_node(node, edge_label_begin , edge_label_end, path_pos);
  256. /* Connect new_leaf (4) as the new son of node (1) */
  257. son = node->sons;
  258. while(son->right_sibling != 0)
  259. son = son->right_sibling;
  260. connect_siblings(son, new_leaf);
  261. /* return (4) */
  262. returnnew_leaf;
  263. }
  264. /*-------split-------*/
  265. #ifdef DEBUG
  266. printf("rule 2: split (%lu,%lu)\n",edge_label_begin,edge_label_end);
  267. #endif
  268. /* Create a new internal node (3) at the split point */
  269. new_internal = create_node(
  270. node->father,
  271. node->edge_label_start,
  272. node->edge_label_start+edge_pos,
  273. node->path_position);
  274. /* Update the node (1) incoming edge starting index (it now starts where node
  275. (3) incoming edge ends) */
  276. node->edge_label_start += edge_pos+1;
  277. /* Create a new leaf (2) with the characters of the extension */
  278. new_leaf = create_node(
  279. new_internal,
  280. edge_label_begin,
  281. edge_label_end,
  282. path_pos);
  283. /* Connect new_internal (3) where node (1) was */
  284. /* Connect (3) with (1)'s left sibling */
  285. connect_siblings(node->left_sibling, new_internal);
  286. /* connect (3) with (1)'s right sibling */
  287. connect_siblings(new_internal, node->right_sibling);
  288. node->left_sibling = 0;
  289. /* Connect (3) with (1)'s father */
  290. if(new_internal->father->sons == node)
  291. new_internal->father->sons = new_internal;
  292. /* Connect new_leaf (2) and node (1) as sons of new_internal (3) */
  293. new_internal->sons = node;
  294. node->father = new_internal;
  295. connect_siblings(node, new_leaf);
  296. /* return (3) */
  297. returnnew_internal;
  298. }
  299. /******************************************************************************/
  300. /*
  301. trace_single_edge :
  302. Traces for a string in a given node's OUTcoming edge. It searches only in the
  303. given edge and not other ones. Search stops when either whole string was
  304. found in the given edge, a part of the string was found but the edge ended
  305. (and the next edge must be searched too - performed by function trace_string)
  306. or one non-matching character was found.
  307. Input : The string to be searched, given in indices of the main string.
  308. Output: (by value) the node where tracing has stopped.
  309. (by reference) the edge position where last match occured, the string
  310. position where last match occured, number of characters found, a flag
  311. for signaling whether search is done, and a flag to signal whether
  312. search stopped at a last character of an edge.
  313. */
  314. NODE* trace_single_edge(
  315. SUFFIX_TREE*    tree,
  316. /* Node to start from */
  317. NODE*           node,
  318. /* String to trace */
  319. PATH            str,
  320. /* Last matching position in edge */
  321. DBL_WORD*       edge_pos,
  322. /* Last matching position in tree source string */
  323. DBL_WORD*       chars_found,
  324. /* Skip or no_skip*/
  325. SKIP_TYPE       type,
  326. /* 1 if search is done, 0 if not */
  327. int*            search_done)
  328. {
  329. NODE*      cont_node;
  330. DBL_WORD   length,str_len;
  331. /* Set default return values */
  332. *search_done = 1;
  333. *edge_pos    = 0;
  334. /* Search for the first character of the string in the outcoming edge of
  335. node */
  336. cont_node = find_son(tree, node, tree->tree_string[str.begin]);
  337. if(cont_node == 0)
  338. {
  339. /* Search is done, string not found */
  340. *edge_pos = get_node_label_length(tree,node)-1;
  341. *chars_found = 0;
  342. returnnode;
  343. }
  344. /* Found first character - prepare for continuing the search */
  345. node    = cont_node;
  346. length  = get_node_label_length(tree,node);
  347. str_len = str.end - str.begin + 1;
  348. /* Compare edge length and string length. */
  349. /* If edge is shorter then the string being searched and skipping is
  350. enabled - skip edge */
  351. if(type == skip)
  352. {
  353. if(length <= str_len)
  354. {
  355. (*chars_found)   = length;
  356. (*edge_pos)      = length-1;
  357. if(length < str_len)
  358. *search_done  = 0;
  359. }
  360. else
  361. {
  362. (*chars_found)   = str_len;
  363. (*edge_pos)      = str_len-1;
  364. }
  365. #ifdef STATISTICS
  366. counter++;
  367. #endif
  368. returnnode;
  369. }
  370. else
  371. {
  372. /* Find minimum out of edge length and string length, and scan it */
  373. if(str_len < length)
  374. length = str_len;
  375. for(*edge_pos=1, *chars_found=1; *edge_pos
  376. {
  377. #ifdef STATISTICS
  378. counter++;
  379. #endif
  380. /* Compare current characters of the string and the edge. If equal -
  381. continue */
  382. if(tree->tree_string[node->edge_label_start+*edge_pos] != tree->tree_string[str.begin+*edge_pos])
  383. {
  384. (*edge_pos)--;
  385. returnnode;
  386. }
  387. }
  388. }
  389. /* The loop has advanced *edge_pos one too much */
  390. (*edge_pos)--;
  391. if((*chars_found) < str_len)
  392. /* Search is not done yet */
  393. *search_done = 0;
  394. returnnode;
  395. }
  396. /******************************************************************************/
  397. /*
  398. trace_string :
  399. Traces for a string in the tree. This function is used in construction
  400. process only, and not for after-construction search of substrings. It is
  401. tailored to enable skipping (when we know a suffix is in the tree (when
  402. following a suffix link) we can avoid comparing all symbols of the edge by
  403. skipping its length immediately and thus save atomic operations - see
  404. Ukkonen's algorithm, skip trick).
  405. This function, in contradiction to the function trace_single_edge, 'sees' the
  406. whole picture, meaning it searches a string in the whole tree and not just in
  407. a specific edge.
  408. Input : The string, given in indice of the main string.
  409. Output: (by value) the node where tracing has stopped.
  410. (by reference) the edge position where last match occured, the string
  411. position where last match occured, number of characters found, a flag
  412. for signaling whether search is done.
  413. */
  414. NODE* trace_string(
  415. SUFFIX_TREE*    tree,
  416. /* Node to start from */
  417. NODE*           node,
  418. /* String to trace */
  419. PATH            str,
  420. /* Last matching position in edge */
  421. DBL_WORD*       edge_pos,
  422. /* Last matching position in tree string */
  423. DBL_WORD*       chars_found,
  424. /* skip or not */
  425. SKIP_TYPE       type)
  426. {
  427. /* This variable will be 1 when search is done.
  428. It is a return value from function trace_single_edge */
  429. intsearch_done = 0;
  430. /* This variable will hold the number of matching characters found in the
  431. current edge. It is a return value from function trace_single_edge */
  432. DBL_WORD edge_chars_found;
  433. *chars_found = 0;
  434. while(search_done == 0)
  435. {
  436. *edge_pos        = 0;
  437. edge_chars_found = 0;
  438. node = trace_single_edge(tree, node, str, edge_pos, &edge_chars_found, type, &search_done);
  439. str.begin       += edge_chars_found;
  440. *chars_found    += edge_chars_found;
  441. }
  442. returnnode;
  443. }
  444. /******************************************************************************/
  445. /*
  446. ST_FindSubstring :
  447. See suffix_tree.h for description.
  448. */
  449. DBL_WORD ST_FindSubstring(
  450. /* The suffix array */
  451. SUFFIX_TREE*    tree,
  452. /* The substring to find */
  453. char*  W,
  454. /* The length of W */
  455. DBL_WORD        P)
  456. {
  457. /* Starts with the root's son that has the first character of W as its
  458. incoming edge first character */
  459. NODE* node   = find_son(tree, tree->root, W[0]);
  460. DBL_WORD k,j = 0, node_label_en

數(shù)據(jù)分析咨詢請(qǐng)掃描二維碼

若不方便掃碼,搜微信號(hào):CDAshujufenxi

數(shù)據(jù)分析師資訊
更多

OK
客服在線
立即咨詢
客服在線
立即咨詢
') } function initGt() { var handler = function (captchaObj) { captchaObj.appendTo('#captcha'); captchaObj.onReady(function () { $("#wait").hide(); }).onSuccess(function(){ $('.getcheckcode').removeClass('dis'); $('.getcheckcode').trigger('click'); }); window.captchaObj = captchaObj; }; $('#captcha').show(); $.ajax({ url: "/login/gtstart?t=" + (new Date()).getTime(), // 加隨機(jī)數(shù)防止緩存 type: "get", dataType: "json", success: function (data) { $('#text').hide(); $('#wait').show(); // 調(diào)用 initGeetest 進(jìn)行初始化 // 參數(shù)1:配置參數(shù) // 參數(shù)2:回調(diào),回調(diào)的第一個(gè)參數(shù)驗(yàn)證碼對(duì)象,之后可以使用它調(diào)用相應(yīng)的接口 initGeetest({ // 以下 4 個(gè)配置參數(shù)為必須,不能缺少 gt: data.gt, challenge: data.challenge, offline: !data.success, // 表示用戶后臺(tái)檢測(cè)極驗(yàn)服務(wù)器是否宕機(jī) new_captcha: data.new_captcha, // 用于宕機(jī)時(shí)表示是新驗(yàn)證碼的宕機(jī) product: "float", // 產(chǎn)品形式,包括:float,popup width: "280px", https: true // 更多配置參數(shù)說(shuō)明請(qǐng)參見:http://docs.geetest.com/install/client/web-front/ }, handler); } }); } function codeCutdown() { if(_wait == 0){ //倒計(jì)時(shí)完成 $(".getcheckcode").removeClass('dis').html("重新獲取"); }else{ $(".getcheckcode").addClass('dis').html("重新獲取("+_wait+"s)"); _wait--; setTimeout(function () { codeCutdown(); },1000); } } function inputValidate(ele,telInput) { var oInput = ele; var inputVal = oInput.val(); var oType = ele.attr('data-type'); var oEtag = $('#etag').val(); var oErr = oInput.closest('.form_box').next('.err_txt'); var empTxt = '請(qǐng)輸入'+oInput.attr('placeholder')+'!'; var errTxt = '請(qǐng)輸入正確的'+oInput.attr('placeholder')+'!'; var pattern; if(inputVal==""){ if(!telInput){ errFun(oErr,empTxt); } return false; }else { switch (oType){ case 'login_mobile': pattern = /^1[3456789]\d{9}$/; if(inputVal.length==11) { $.ajax({ url: '/login/checkmobile', type: "post", dataType: "json", data: { mobile: inputVal, etag: oEtag, page_ur: window.location.href, page_referer: document.referrer }, success: function (data) { } }); } break; case 'login_yzm': pattern = /^\d{6}$/; break; } if(oType=='login_mobile'){ } if(!!validateFun(pattern,inputVal)){ errFun(oErr,'') if(telInput){ $('.getcheckcode').removeClass('dis'); } }else { if(!telInput) { errFun(oErr, errTxt); }else { $('.getcheckcode').addClass('dis'); } return false; } } return true; } function errFun(obj,msg) { obj.html(msg); if(msg==''){ $('.login_submit').removeClass('dis'); }else { $('.login_submit').addClass('dis'); } } function validateFun(pat,val) { return pat.test(val); }