??xml version="1.0" encoding="utf-8" standalone="yes"?>国内精品免费久久影院,国产精品va久久久久久久,美女久久久久久http://www.shnenglu.com/tgh621/category/8152.html专注技术开?/description>zh-cnWed, 14 Jan 2009 06:14:40 GMTWed, 14 Jan 2009 06:14:40 GMT60用WaitForSingleObject{待事g处理http://www.shnenglu.com/tgh621/archive/2009/01/12/71782.html大v大vMon, 12 Jan 2009 02:17:00 GMThttp://www.shnenglu.com/tgh621/archive/2009/01/12/71782.htmlhttp://www.shnenglu.com/tgh621/comments/71782.htmlhttp://www.shnenglu.com/tgh621/archive/2009/01/12/71782.html#Feedback0http://www.shnenglu.com/tgh621/comments/commentRss/71782.htmlhttp://www.shnenglu.com/tgh621/services/trackbacks/71782.html 1void ClearMessage(HWND hWnd,BOOL bExtMsg)
 2{
 3    MSG GetMsg;
 4    while(PeekMessage(&GetMsg,hWnd,0,0,PM_REMOVE))
 5    {        
 6        if(GetMsg.message == WM_TIMER) continue;
 7        TranslateMessage(&GetMsg);
 8        DispatchMessage(&GetMsg);
 9    }
            
10    if(hWnd != NULL && bExtMsg)
11    {    
12        while(PeekMessage(&GetMsg,NULL,WM_WINDOWPOSCHANGING,WM_WINDOWPOSCHANGED,PM_REMOVE))
13        {        
14            TranslateMessage(&GetMsg);
15            DispatchMessage(&GetMsg);
16        }
                                
17        while(PeekMessage(&GetMsg,NULL,0,0,PM_QS_PAINT))
18        {        
19            TranslateMessage(&GetMsg);
20            DispatchMessage(&GetMsg);
21        }

22    }

23}

24
25void CExportRegeditToXml::OnBnClickedCancel()
26{
27
28
29    if ( ( NULL != m_TransRegedit )  && ( !pThreadData->m_brepalce) ) 
30    {
31        if(MessageBox(_T("目前正在导出注册表,是否取消!"),_T("警告"),MB_YESNO)!=IDYES)
32            return;
33        pThreadData->m_brepalce = TRUE;
34
35        while (m_TransRegedit && WaitForSingleObject(m_TransRegedit->m_hThread,40)!=WAIT_OBJECT_0) 
36        {
37            ClearMessage(NULL, TRUE);
38        }

39        m_TransRegedit = NULL;
40    }

41
42    OnCancel();
43}


大v 2009-01-12 10:17 发表评论
]]>
【{】字W串匚w法Q四Q可以滑动多q?/title><link>http://www.shnenglu.com/tgh621/archive/2008/11/11/66596.html</link><dc:creator>大v</dc:creator><author>大v</author><pubDate>Tue, 11 Nov 2008 05:09:00 GMT</pubDate><guid>http://www.shnenglu.com/tgh621/archive/2008/11/11/66596.html</guid><wfw:comment>http://www.shnenglu.com/tgh621/comments/66596.html</wfw:comment><comments>http://www.shnenglu.com/tgh621/archive/2008/11/11/66596.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/tgh621/comments/commentRss/66596.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/tgh621/services/trackbacks/66596.html</trackback:ping><description><![CDATA[     摘要: 记得在穷举法中,每一比较后Q无论成与不成,都将模式向右滑动一个位|,然后l箋比较。有没有办法能利用之前的比较l果Q得模式滑动的更远一点呢Q? 在介l经典的KMP法前,我先介绍几个单的滑动cȝ法? Not So Naive 同名字一Pq个法的确有点q稚Q它Ҏ(gu)模式的前两个字符是否相同来滑动比ID法稍长一点的距离Q如果前两个字符相同Q那么文本中与第二个字符不同则必然也与第一...  <a href='http://www.shnenglu.com/tgh621/archive/2008/11/11/66596.html'>阅读全文</a><img src ="http://www.shnenglu.com/tgh621/aggbug/66596.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/tgh621/" target="_blank">大v</a> 2008-11-11 13:09 <a href="http://www.shnenglu.com/tgh621/archive/2008/11/11/66596.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> 【{】字W串匚w法Q三Q位q算的魔法——KR与SOhttp://www.shnenglu.com/tgh621/archive/2008/11/11/66595.html大v大vTue, 11 Nov 2008 05:08:00 GMThttp://www.shnenglu.com/tgh621/archive/2008/11/11/66595.htmlhttp://www.shnenglu.com/tgh621/comments/66595.htmlhttp://www.shnenglu.com/tgh621/archive/2008/11/11/66595.html#Feedback0http://www.shnenglu.com/tgh621/comments/commentRss/66595.htmlhttp://www.shnenglu.com/tgh621/services/trackbacks/66595.html位运经常能做出一些不可思议的事情来Q例如不用时变量要交换两个数该怎么做呢Q一个没接触q这c问题的人打M也想不出来。如果拿围棋来做比喻Q那么位q算可以Mؓ~程中的“手筋”?/div>

按位的存储方式能提供最大的存储I间利用率,而随着I间被压~的同时Q由于CPUg的直接支持,速度竟然奇般的提升了。D个例子,普通的数组要实现移位操作,那是O(n)的时间复杂度Q而如果用位运中的移位,是一个指令搞定了?/div>

KR法

KR法之前W一章介l中说是利用哈希Q原文这么介l的。而我的看法是Q哈希只是一个幌子。这个算法的基本步骤同穷举法一P不同在于每趟比较前先比较一下哈希|hashg同就不必比较了。而如果hash值无法高效计,q样的改q甚臌不如不改q呢。你xQ比较之前还要先计算一遍hash|有计的功夫Q直接比都比完了?/div>

KR法Z把挨个字W的比较转化Z个整数的比较Q它把一个m长度的字W串直接当成一个整数来对待Q以2为基数的整数。这样呢Q在W一ơ算个整数后Q以后每ơ移动窗口,只需要移L高位Q再加上最低位Q就得出一个新的hash倹{但是m太大Q导致超机所能处理的最大整数怎么办?不用担心Q对整数最大值取模,借助模运的Ҏ(gu),一切可以完的q行。而且׃是对整数最大值取模,所以取模这一步都可以忽略掉?/div>

q是KR法的代码:
  1. #define REHASH(a, b, h) ((((h) - (a)*d) << 1) + (b))
  2. void KR(char *x, int m, char *y, int n) {
  3.    int d, hx, hy, i, j;
  4.    /* Preprocessing */
  5.    /* computes d = 2^(m-1) with
  6.       the left-shift operator */
  7.    for (d = i = 1; i < m; ++i)
  8.       d = (d<<1);
  9.    for (hy = hx = i = 0; i < m; ++i) {
  10.       hx = ((hx<<1) + x[i]);
  11.       hy = ((hy<<1) + y[i]);
  12.    }
  13.    /* Searching */
  14.    j = 0;
  15.    while (j <= n-m) {
  16.       if (hx == hy && memcmp(x, y + j, m) == 0)
  17.          OUTPUT(j);
  18.       hy = REHASH(y[j], y[j + m], hy);
  19.       ++j;
  20.    }
  21. }
我们可以看到QKR法有O(m)复杂度的预处理的q程QL觉它的预处理没有反映出模式本w的特点来,D它的搜烦q程依然是O(mn)复杂度的Q只不过一般情况下体现不出来,?aaaaaaaaaaaaaaaaaaaaaaaaa"中搜"aaaaa"q道KR多慢了?/div>

ȝ来说QKR法比穷丑ּ一点,比较ơ数的期望值是O(m+n)?/div>

Shift Or 法

Z最大限度的发挥Zq算的能力,Shift Or法有了一个最大缺P模式不能过机器字长。按现在普遍?2位机Q机器字长就?2Q也是只能用来匚w不大?2个字W的模式。而带来的好处是匚wq程是O(n)旉复杂度的Q达到自动机的速度了。而预处理所p的时间与I间都ؓO(m+σ)Q比自动机少多了?/div>

我们来看看它怎么巧妙的实?#8220;只看一?#8221;的:

假设我们有一个升U系l,d有m个别。每一关都会放一个新人到W?U上Q然后对于系l中所有的人,如果通过考验Q升一U,否则Q咔嚓掉。而对于升到最高的hQ那说明他连l通过了mơ考验Q这是我们要选拔的h?/div>

KR法的思\是上面的升U规则,l出的考验是你的位置上的字符与给出的文本字符是否一致。升满了,说明在连lm个位|上与不断给出的文本字符一_q也是匚w成功了?/div>

明白了这个思\后,疑问开始出来了Q检查哪些位|与文本字符一_需要mơ吧Q那么整个算法就是O(mn)了?

现在p位运出ZQ对Q这个算法的思\是很W,但是我位q算的效率高呀Q事先我出字母表中每个字符在模式中出现的位|,用位的方式存在整数里Q出现的地方标ؓ0Q不出现的地Ҏ(gu)?Q这hd使用σ个整敎ͼ同样Q我用一个整数来表示升状态,某个U别有h标?Q没人就标ؓ1Q整个系l升U就恰好可以?#8220;UM”来进行,当检查位|的时候只需要与表示状态的整数“?#8221;1ơ,所以整个算法就成O(n)了。Shift-Or法名字是q样来的?/div>

有一个地方很奇怪,0?的设定和通常的习惯相反呀Q习惯上Q喜Ƣ把存在设ؓ1Q不存在设ؓ0的。不q这里没有办法,因ؓUM新移出来的是0?/div>

q时我们来看代码容易理解多了:
  1. #define WORDSIZE sizeof(int)*8
  2. #define ASIZE 256
  3. int preSo(const char *x, int m, unsigned int S[]) {
  4.         unsigned int j, lim;
  5.         int i;
  6.         for (i = 0; i < ASIZE; ++i)
  7.                 S[i] = ~0;
  8.         for (lim = i = 0, j = 1; i < m; ++i, j <<= 1) {
  9.                 S[x[i]] &= ~j;
  10.                 lim |= j;
  11.         }
  12.         lim = ~(lim>>1);
  13.         return(lim);
  14. }
  15. void SO(const char *x, int m, const char *y, int n) {
  16.         unsigned int lim, state;
  17.         unsigned int S[ASIZE];
  18.         int j;
  19.         if (m > WORDSIZE)
  20.                 error("SO: Use pattern size <= word size");
  21.         /* Preprocessing */
  22.         lim = preSo(x, m, S);
  23.         /* Searching */
  24.         for (state = ~0, j = 0; j < n; ++j) {
  25.                 state = (state<<1) | S[y[j]];
  26.                 if (state < lim)
  27.                         OUTPUT(j - m + 1);
  28.         }
  29. }
代码中lim变量其实是一个标,例如出现最高的状态是01111111Q那么lim成?0000000Q因此只要小于limQ就表示最高上的0出现了?

原文中对Shift-Or法的描q还是很难懂的,如果对着那段说明ȝ代码Q有点不知所云的感觉。我q是直接对着代码才想个升U的比喻来?/div>

大v 2008-11-11 13:08 发表评论
]]> [转]字符串匹配算法(二)ID与自动机http://www.shnenglu.com/tgh621/archive/2008/11/11/66594.html大v大vTue, 11 Nov 2008 05:07:00 GMThttp://www.shnenglu.com/tgh621/archive/2008/11/11/66594.htmlhttp://www.shnenglu.com/tgh621/comments/66594.htmlhttp://www.shnenglu.com/tgh621/archive/2008/11/11/66594.html#Feedback1http://www.shnenglu.com/tgh621/comments/commentRss/66594.htmlhttp://www.shnenglu.com/tgh621/services/trackbacks/66594.html
Rob Pike, 最伟大的C 语言大师之一, 在《Notes on C Programming》中阐述了一个原则:花哨的算法比单算法更Ҏ(gu)出bug、更隑֮玎ͼ量使用单的法配合单的数据l构。?/span>Ken Thompson——Unix 最初版本的设计者和实现者,宗偈语般地对Pike 的这一原则作了Q?nbsp;拿不准就IDQWhen in doubt , use brute forceQ?/span>?nbsp;而对于装13爱好者来_更是自豪的称其用的是BF法?/span>

ID法用在字W串匚w上,单的描述是Q检查文本从0到n-m的每一个位|,看看从这个位|开始是否与模式匚w。这U方法还是有一些优点的Q如Q不需要预处理q程Q需要的额外I间为常敎ͼ每一比较时可以以Q意顺序进行?br>

管它的旉复杂度ؓO(mn)Q例如在文本"aaaaaaaaaaaaaaaaaaaaaaaaaaa"中寻?aaaaab"Ӟ完全体现出来了。但是算法的期望值却?nQ这表明该算法在实际应用中效率不低?/div>

C代码如下Q?/div>
  1. void BF(char *x, int m, char *y, int n) {
  2.    int i, j;
  3.    /* Searching */
  4.    for (j = 0; j <= n - m; ++j) {
  5.       for (i = 0; i < m && x[i] == y[i + j]; ++i);
  6.       if (i >= m)
  7.          OUTPUT(j);
  8.    }
  9. }
  10.   
如果我们注意到C库函数是汇编优化q的Qƈ通常能提供比C代码更高的性能的话Q我们可以用memcmp来完成每一比较过E,从而达到更好的性能Q?/div>
  1. #define EOS '\0'
  2.    
  3. void BF(char *x, int m, char *y, int n) { 
  4.   char *yb; 
  5.   /* Searching */ 
  6.   for (yb = y; *y != EOS; ++y) 
  7.     if (memcmp(x, y, m) == 0) 
  8.       OUTPUT(y - yb);
  9. }
自动机的Ҏ(gu)其实和穷举法有点怼Q都是用最单直白的方式来做事情。区别在于穷举法是在计算Q而自动机则是查表。尽自动机的构造过E有一点点难解Q要涉及到DFA的理论,但是自动机的比较q程那绝Ҏ(gu)单到无语?/div>

单说来,Ҏ(gu)模式Ԍd了一张大的表|表格m+1?#963;列,q里σ表示字母表的大小。表格每一行表CZU状态,状态数比模式长度多1。一开始的状态是0Q也是处在表格的第0行,q一行的每个元素指示了当遇到某字W时p转到另一个状态。每当蟩转到最l状态时Q表C找C一个匹配?/div>

语言表述hq是比较啰嗦Q看代码q道了Q?/div>
  1. #define ASIZE 256
  2. int preAut(const char *x, int m, int* aut) {
  3.         int i, state, target, old;
  4.         for (state = 0, i = 0; i < m; ++i) {
  5.                 target = i + 1;
  6.                 old = aut[state * ASIZE + x[i]];
  7.                 aut[state * ASIZE + x[i]] = target;
  8.                 memcpy(aut + target * ASIZE, aut + old * ASIZE, ASIZE*sizeof(int));
  9.                 state = target;
  10.         }
  11.         return state;
  12. }
  13. void AUT(const char *x, int m, const char *y, int n) {
  14.         int j, state;
  15.         /* Preprocessing */
  16.         int *aut = (int*)calloc((m+1)*ASIZE, sizeof(int));
  17.         int Terminal = preAut(x, m, aut);
  18.         /* Searching */
  19.         for (state = 0, j = 0; j < n; ++j) {
  20.                 state = aut[state*ASIZE+y[j]];
  21.                 if (state == Terminal)
  22.                         OUTPUT(j - m + 1);
  23.         }
  24. }
Q?span class=Apple-style-span style="COLOR: rgb(51,51,153)">注:原文的代码用一个有向图的数据结构,我遵循大师的指引Q改用了更简单一点的数组Q?br>

从代码上我们很容易看出,自动机的构造需要时间是O(mσ)Q空间也是O(mσ)Q严格来说这份代码用了O((m+1)σ)Q,但是一旦构造完毕,接下来匹配的旉则是O(n)?/div>

匚w的过E前面已l说了,太简单了没什么好说的Q这里就解释一下构造过E吧Q?/div>

我们构造的目标是对应模式长度,构造出同样多的状态,?表示初始状态,然后W一个字W用状?表示Q第二个用状?表示Q依ơ类推,直到最后一个字W,用m表示Q也是最l状态?/div>

一开始,数组全都|?Q,q个时候的自动机遇CQ何字W都转到初始状态。然后给它看模式的第一个字W,假设q是'a'吧,告诉它,状?遇到'a'应该C个新的状态——状?Q所以把W?行的W?a'列修改ؓ1。而这个时候状?q是I白的,怎么办呢Q?/div>

q时候状?想呀Q在我被告知遇到'a'要去状?之前Q我原本遇到'a'都要ȝ?的,也就是修改之前第'a'列所指的那个状态,UCؓold状态吧Q而现在我遇到'a'却要M个新的状态,既然以前old状态能处理遇到'a'之后的事情,那么我让新的状态像old状态一样就好了。于是状?把old状态拷贝到状??/div>

现在轮到状?了,l它看第二个字符Q它也如法炮Ӟ指向了状?Q又把old状态拷贝给了状??/div>

于是Q状态机在q种代代传承的过E中构造完毕了?/div>

虽然理论上自动机是最完美的匹配方式,但是׃预处理的消耗过大,实践中,主要q是用于正则表达式?/div>

l语Q穷举法与自动机各自C两个极端Q因此都没能辑ֈl合性能的最佻I本文之后介绍的算法,可以看成是在ID和自动机两者之间取舍权衡的l果?/div>


大v 2008-11-11 13:07 发表评论
]]>[转]字符串匹配算法(一Q简?/title><link>http://www.shnenglu.com/tgh621/archive/2008/11/11/66593.html</link><dc:creator>大v</dc:creator><author>大v</author><pubDate>Tue, 11 Nov 2008 05:05:00 GMT</pubDate><guid>http://www.shnenglu.com/tgh621/archive/2008/11/11/66593.html</guid><wfw:comment>http://www.shnenglu.com/tgh621/comments/66593.html</wfw:comment><comments>http://www.shnenglu.com/tgh621/archive/2008/11/11/66593.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/tgh621/comments/commentRss/66593.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/tgh621/services/trackbacks/66593.html</trackback:ping><description><![CDATA[<div>文本信息可以说是q今为止最主要的一U信息交换手D,而作为文本处理中的一个重要领域——字W串匚wQ就是我们今天要说的话题。(<span id="mcg0mkk" class=Apple-style-span style="COLOR: rgb(51,51,153)">原文q特意提及文本数据数量每18个月M番,以此法必须要是高效的。不q我注意到摩定律也?8个月ȝQ这正说明数据的增长是紧紧跟随处理速度的,因此是使用高效的算法,来待处理的数据׃多。这也提C屏q前的各位,代码不要写得太快?#8230;…</span>Q?/div> <div><br></div> <div>字符串匹配指的是从文本中扑ևl定字符ԌUCؓ模式Q的一个或所有出现的位置。本文的法一律输出全部的匚w位置。模式串在代码中用x[m]来表C,文本用y[n]来,而所有字W串都构造自一个有限集的字母表ΣQ其大小?#963;?/div> <div><br></div> <div>Ҏ(gu)先给出模式还是先l出文本Q字W串匚w分ؓ两类Ҏ(gu)Q?/div> <div> <ul> <li><span id="oas88eu" class=Apple-style-span style="LINE-HEIGHT: normal">W一cL法基于自动机或者字W串的组合特点,其实CQ通常是对模式q行预处理;</span><br> <li><span id="0yagsqo" class=Apple-style-span style="LINE-HEIGHT: normal">W二cL法对文本建立索引Q这也是现在搜烦引擎采用的方法?/span></li> </ul> 本文仅讨论第一cL法?br></div> <div><br></div> <div>文中的匹配算法都是基于这样一U方式来q行的:设想一个长度ؓm的窗口,首先H口的左端和文本的左端对齐,把窗口中的字W与模式字符q行比较Q这UCؓ一比较,当这一比较完全匹配或者出现失配时Q将H口向右Ud。重复这个过E,直到H口的右端到达了文本的右端。这U方法我们通常叫sliding window?/div> <div><br></div> <div>对于ID法来_扑ֈ所有匹配位|需要的旉为O(mn)Q基于对ID法改q的l果Q我们按照每一比较时的比较顺序,把这些算法分Z下四U:</div> <div> <ol> <li>从左到右Q最自然的方式,也是我们的阅读顺? <li>从右到左Q通常在实践中能生最好的法 <li>Ҏ(gu)序Q可以达到理Z的极? <li>L序Q这些算法跟比较序没关p(例如Q穷举法Q?/li> </ol> </div> <div>一些主要算法的单介l如下:</div> <div><br></div> <div><span id="eu80880" class=Apple-style-span style="FONT-WEIGHT: bold">从左到右</span></div> <div>采用哈希Q可以很Ҏ(gu)在大部分情况下避免二ơ比较,通过合理的假设,q种法是线性时间复杂度的。它最先由Harrison提出Q而后由Karp和Rabin全面分析Q称为KR法?/div> <div>在假设模式长度不大于机器字长ӞShift-Or法是很高效的匹配算法,同时它可以很Ҏ(gu)扩展到模p匹配上?/div> <div>MP是第一个线性时间算法,随后被改qؓKMPQ它的匹配方式很cM于自动机的识别过E,文本的每个字W与模式的每个字W比较不会超qlog<span id="0sc0q00" class=Apple-style-span style="VERTICAL-ALIGN: sub">Φ</span>(m+1)Q这?#934;是黄金分隔比1.618Q而随后发现的cM法——Simon法Q得文本的每个字符比较不超q?+log<span id="g8u00yy" class=Apple-style-span style="VERTICAL-ALIGN: sub">2</span>mQ这三种法在最坏情况下都只?n-1ơ比较。(<span id="wys00k8" class=Apple-style-span style="COLOR: rgb(51,51,153)">抱歉限于我的水^q一D|没看懂也没能查证Q大家就看个意思吧</span>Q?/div> <div>Z定性有限自动机的算法对文本字符刚好只用nơ访问,但是它需要额外的<span id="e0qke8w" class=Apple-style-span style="FONT-FAMILY: 'Times New Roman'">O(mσ)</span>的空间?/div> <div>一U叫Forward Dawg Matching的算法同样也只用nơ访问,它用了模式的后~自动机?/div> <div>Apostolico-Crochemore法是一U简单算法,最坏情况下也只需?n/2ơ比较?br></div> <div>q有一U不那么q稚QNot So NaiveQ的法Q最坏情况下是nqxQ但是预处理q程的时间和I间均ؓ常数Q而且q_情况下的性能非常接近U性?/div> <div><br></div> <div><span id="ss8qw8q" class=Apple-style-span style="FONT-WEIGHT: bold">从右到左</span></div> <div>BM法被认为是通常应用中最有效率的法了,它或者它的简化版本常用于文本~辑器中的搜索和替换功能Q对于非周期性的模式而言Q?n是这U算法的比较ơ数上界了,不过对于周期性模式,它最坏情况下需要n的二ơ方?/div> <div>BM法的一些变U避免了原算法的二次斚w题,比较高效的有QApostolico and Giancarlo法、Turbo BM法和Reverse Colussi法?/div> <div>实验的结果表明,Quick Search法QBM的一个变U)以及Z后缀自动机的Reverse Factor和Turbo Reverse Factor法是实践中最有效的算法了?br></div> <div>Zhu and Takaoka法和BR法也是BM的变U,它们则需?span class=Apple-style-span style="FONT-FAMILY: 'Times New Roman'">O(σ</span><span id="cegm8s8" class=Apple-style-span style="FONT-FAMILY: 'Times New Roman'"><span id="akw088k" class=Apple-style-span style="VERTICAL-ALIGN: super">2</span></span><span id="08ke0c0" class=Apple-style-span style="FONT-FAMILY: 'Times New Roman'">)</span>的额外空间?/div> <div><br></div> <div><span id="acgkkig" class=Apple-style-span style="FONT-WEIGHT: bold">Ҏ(gu)序</span></div> <div>最先达到空间线性最优的是Galil-Seiferas和Two Way法Q它们把模式分ؓ两部分,先从左到x索右边的部分Q如果没有失配,再搜索左边的部分?/div> <div>Colussi和Galil-Giancarlo法模式位|分Z个子集,先从左至x索第一个子集,如果没有失配Q再搜烦剩下的。Colussi法作ؓKMP法的改q,使得最坏情况下只需?n/2ơ比较,而Galil-Giancarlo法则通过改进Colussi法的一个特D情况,把最坏比较次数减到?n/3?/div> <div>最?jng)_配和M最大位Uȝ法分别根据模式的字符频率和首字位U,Ҏ(gu)式位|进行排序?br></div> <div>Skip SearchQKMP Skip Search和Alpha Skip Search法q用“?#8221;的方法来军_模式的v始位|?br></div> <div><br></div> <div><span id="ya8w88q" class=Apple-style-span style="FONT-WEIGHT: bold">L序</span></div> <div><span id="e080gmm" class=Apple-style-span style="FONT-WEIGHT: bold"><span id="cwwco88" class=Apple-style-span style="FONT-WEIGHT: normal">Horspool法也是BM的一个变U,它用一U移位函敎ͼ而与字符比较序不相qӀ还有其他的变种如:</span><span id="i0a0o0k" class=Apple-style-span style="FONT-WEIGHT: normal">Quick Search法Q?/span><span id="u80yec0" class=Apple-style-span style="FONT-WEIGHT: normal">Tuned Boyer-Moore法Q?/span><span id="sc8080u" class=Apple-style-span style="FONT-WEIGHT: normal">Smith法Q?/span><span id="m0w000a" class=Apple-style-span style="FONT-WEIGHT: normal">Raita法?/span><br></span></div> <div><br></div> <div>在接下来的章节中Q我们会l出上面q些法的实现。我们把字母表限定ؓASCII码或者它的Q意子集,~程语言用CQ这意味着数组索引是从0开始,而字W串以NULLl尾?/div> <div><br></div> <div>Q?span class=Apple-style-span style="COLOR: rgb(51,51,153)">W一章完。好像这些算法被挨个怺个遍Q反而不知道该选哪一U了Q老外介绍别h的东西时是q样Q尽来虚的?/span>Q?/div> <img src ="http://www.shnenglu.com/tgh621/aggbug/66593.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/tgh621/" target="_blank">大v</a> 2008-11-11 13:05 <a href="http://www.shnenglu.com/tgh621/archive/2008/11/11/66593.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Z?char** 不能自动转化?const char** (? http://www.shnenglu.com/tgh621/archive/2008/11/11/66588.html大v大vTue, 11 Nov 2008 03:23:00 GMThttp://www.shnenglu.com/tgh621/archive/2008/11/11/66588.htmlhttp://www.shnenglu.com/tgh621/comments/66588.htmlhttp://www.shnenglu.com/tgh621/archive/2008/11/11/66588.html#Feedback0http://www.shnenglu.com/tgh621/comments/commentRss/66588.htmlhttp://www.shnenglu.com/tgh621/services/trackbacks/66588.html

一ơ偶然的情况下我发现以下代码竟然无法被编译通过Q如果你的编译器Q比如VC6或VC2003Q允许它~译通过Q我想你首先应该换个~译器,比如GCC或VC2005Q:
void foo( const char* [] ) { }
int main( void )
{
    char* s[2];
    foo( s );
}

化成更一般的形式是:
char** p1 = 0;
const char** p2 = p1;

错误是:invalid conversion from `char**' to `const char**'.

lostpencil更加仔细Q用C~译器给出的是一个警告:
initialization from incompatible pointer type.

随后hphol出了合理的解释Q同?a target=_blank>comp.lang.c++.moderated上的Ulrich Eckhardt也用代码q行了说明?/p>

用代码来说明最直观了:
const char* s = "abc";
int main( void )
{
    char* p0 = 0;
    char** p1 = &p0;
    const char** p2 = p1;
// 先假设这一句是合法?( 试Ӟ可以先强制类?strong style="COLOR: black; BACKGROUND-COLOR: #99ff99">?/strong>化一?)
    *p2 = s;
    *p0 = 'A';
// 通过p0在修改不应该被修改的sQ这昄?strong style="COLOR: black; BACKGROUND-COLOR: #ffff66">const相违背,其运行结果不可知?br>}




看了 **?惛_?br>tekyDec 29, 2005 -  Show original item

看完?明白**讲的Z?strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">char** 不能自动?/strong>化ؓ const char**,(原文)但对我媄响最q是下面的?

==================================================================
char *p="abc" 能不能编译通过要看你用的~译器。鉴于大量遗留代码的存在Q大部分~译器允许其通过Q或者给个警告。当ӞE序员自己必M证绝不去修改其倹{?

E序员不应该在代码中出现*p='A'q样的语句。这是当初约定好了的Q编译器允许char *p="abc"通过Q而程序员保证不去修改它?
b. *p='A'~译时应该允讔R过Q因为单p条语句而言Q它完全合法?
c. q行?p='A'能不能通过要看实际的运行环境,包括你用的操作pȝ、编译器、编译器选项 {等Q一句话Q其q行l果׃得你Q且不应该由你去兛_Q因U行为本w已l违反约定了?
==================================================================

工作关系?用CString 和string用的太多?很少q样定义字符?char *p=“abcde“?br>匝一?q不适应,:(,渐渐的回x惌v一些来(?q是太生?赶快写下?以后别忘?

q样定义的字W串char *p=“abcde“ ; char *p1=“123445667“;

正如上面提到的是不能?*p='A',q行的时候会出错,同样,strcpy(p,p1)也会出错?

"abcde"字符串可以看做是个常量字W串?是不能被修改?

但如?char p[]=“abcde“ q样定义,没有问?你可以修?p='A',只要不越界就ok.

q且发现q样两种定义
char *p=“abcde“

char p[]=“abcde“

在运行的时?p指向的地址也不是一L,可见char *p=“abcde“q是有特D的处理 :),具体怎么处理׃知道?高手h?)


随着试,又发C问题,可能是个老问题了?


int main(int argc, char* argv[])
{
 int t[10];
 char p1[7]="123456";
 const char *p2="1234567890123213123";
 
 int len(0);
 
  //*p1='C';  err

 len=strlen(p1);
 printf("%d\n",len);
 
 strcpy(p1,p2);   ///??????????
 
 printf("%s\n",p1);
 
 len=strlen(p1);
 
 printf("%d\n",len);
 return 0;
}

我定义的?个字W数l? 但用strcpy把p2拷到p1?p1是放不下?但程序却正常执行,warning ,err都没?q行也正?


输出

6
1234567890123213123
19

应该是用内存越界了??怎么会正常运行呢?

N对于内存界的?q气好才崩溃表现出来,q气不好正常运??

posted on 2006-02-22 13:04 Vincent.Chen 阅读(232) 评论(0)  ~辑  收藏 所属分c? ?/font>



大v 2008-11-11 11:23 发表评论
]]>[ 转]C++cd转换W的使用 http://www.shnenglu.com/tgh621/archive/2008/09/27/62926.html大v大vSat, 27 Sep 2008 10:13:00 GMThttp://www.shnenglu.com/tgh621/archive/2008/09/27/62926.htmlhttp://www.shnenglu.com/tgh621/comments/62926.htmlhttp://www.shnenglu.com/tgh621/archive/2008/09/27/62926.html#Feedback0http://www.shnenglu.com/tgh621/comments/commentRss/62926.htmlhttp://www.shnenglu.com/tgh621/services/trackbacks/62926.htmlC++的四个类型{换运符已经有很久了,但一直没有弄清楚它们的用?今天看到一本书上的解释,才大致地的了解了其具体的用法.

具体归纳如下:

reinterpret_cast

该函数将一个类型的指针转换为另一个类型的指针.
q种转换不用修改指针变量值存放格?不改变指针变量?,只需在编译时重新解释指针的类型就可做?
reinterpret_cast 可以指针D{换ؓ一个整型数,但不能用于非指针cd的{?
?
//基本cd指针的类型{?br>double d=9.2;
double* pd = &d;
int *pi = reinterpret_cast<int*>(pd);  //相当于int *pi = (int*)pd;

//不相关的cȝ指针的类型{?br>class A{};
class B{};
A* pa = new A;
B* pb = reinterpret_cast<B*>(pa);   //相当于B* pb = (B*)pa;

//指针转换为整?br>long l = reinterpret_cast<long>(pi);   //相当于long l = (long)pi;


const_cast

该函数用于去除指针变量的帔R属性,它转换Z个对应指针类型的普通变量。反q来Q也可以一个非帔R的指针变量{换ؓ一个常指针变量?br>q种转换是在~译期间做出的类型更攏V?br>例:
const int* pci = 0;
int* pk = const_cast<int*>(pci);  //相当于int* pk = (int*)pci;

const A* pca = new A;
A* pa = const_cast<A*>(pca);     //相当于A* pa = (A*)pca;

Z安全性考虑Qconst_cast无法非指针的常量{换ؓ普通变量?/p>


static_cast

该函C要用于基本类型之间和hl承关系的类型之间的转换?br>q种转换一般会更改变量的内部表C方式,因此Qstatic_cast应用于指针类型{换没有太大意义?br>例:
//基本cd转换
int i=0;
double d = static_cast<double>(i);  //相当?double d = (double)i;

//转换l承cȝ对象为基cd?br>class Base{};
class Derived : public Base{};
Derived d;
Base b = static_cast<Base>(d);     //相当?Base b = (Base)d;


dynamic_cast

它与static_cast相对Q是动态{换?br>q种转换是在q行时进行{换分析的Qƈ非在~译时进行,明显区别于上面三个类型{换操作?br>该函数只能在l承cd象的指针之间或引用之间进行类型{换。进行{换时Q会Ҏ(gu)当前q行时类型信息,判断cd对象之间的{换是否合法。dynamic_cast的指针{换失败,可通过是否为null,引用转换p|则抛Z个bad_cast异常?br>例:
class Base{};
class Derived : public Base{};

//zcL针{换ؓ基类指针
Derived *pd = new Derived;
Base *pb = dynamic_cast<Base*>(pd);

if (!pb)
 cout << "cd转换p|" << endl;

//没有l承关系Q但被{换类有虚函数
class A(virtual ~A();)   //有虚函数
class B{}:
A* pa = new A;
B* pb  = dynamic_cast<B*>(pa);

如果Ҏ(gu)l承关系或者没有虚函数的对象指针进行{换、基本类型指针{换以及基cL针{换ؓzcL针,都不能通过~译?br>



大v 2008-09-27 18:13 发表评论
]]>
UNICODE串{换成charcd串的四种Ҏ(gu)[转]http://www.shnenglu.com/tgh621/archive/2008/09/27/62924.html大v大vSat, 27 Sep 2008 10:11:00 GMThttp://www.shnenglu.com/tgh621/archive/2008/09/27/62924.htmlhttp://www.shnenglu.com/tgh621/comments/62924.htmlhttp://www.shnenglu.com/tgh621/archive/2008/09/27/62924.html#Feedback0http://www.shnenglu.com/tgh621/comments/commentRss/62924.htmlhttp://www.shnenglu.com/tgh621/services/trackbacks/62924.html1. 调用 WideCharToMultiByte() API

int WideCharToMultiByte (
    UINT    CodePage,                
//1 Unicode~码的字W页QUnicode~码有字W页的概念,比如gb2312/936Qbig5/950{?/span>
    DWORD   dwFlags,                //2 如何处理复合unicode字符Q详l查google
    LPCWSTR lpWideCharStr,        //3 待{换的unicode?/span>
    int     cchWideChar,                //4 表示参数3的长?nbsp; 传?1表示?x00l尾
    LPSTR   lpMultiByteStr,            //5 接受转换后的串的字符~冲
    int     cbMultiByte,                    //6 表示参数5lpMutiByteStr的字节大?nbsp;通常sizeof一?/span>
    LPCSTR  lpDefaultChar,        //7 NULL 具体google
    LPBOOL  lpUsedDefaultChar//8 NULL 具体google
);

2. 调用CRT函数wcstombs()

size_t wcstombs (
    
char*          mbstr,
    
const wchar_t* wcstr,
    size_t         count );

3. 使用CString构造器或赋值操?/p>

// 假设有一个Unicode串wszSomeString

CString str1 ( wszSomeString ); 
// 用构造器转换
CString str2;

str2 
= wszSomeString; // 用赋值操作{?/span>

4. 使用ATL串{换宏

#include <atlconv.h>

// q是假设有一个Unicode串wszSomeString

{
    
char szANSIString [MAX_PATH];
    USES_CONVERSION; 
// 声明q个宏要使用的局部变?/span>

    lstrcpy ( szANSIString, OLE2A(wszSomeString) );
}



大v 2008-09-27 18:11 发表评论
]]>
C++虚函数表解析(? http://www.shnenglu.com/tgh621/archive/2008/09/18/62212.html大v大vThu, 18 Sep 2008 10:54:00 GMThttp://www.shnenglu.com/tgh621/archive/2008/09/18/62212.htmlhttp://www.shnenglu.com/tgh621/comments/62212.htmlhttp://www.shnenglu.com/tgh621/archive/2008/09/18/62212.html#Feedback0http://www.shnenglu.com/tgh621/comments/commentRss/62212.htmlhttp://www.shnenglu.com/tgh621/services/trackbacks/62212.html

C++中的虚函数的作用主要是实C多态的机制。关于多态,而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子cȝ成员函数。这U技术可以让父类的指针有“多种形?#8221;Q这是一U泛型技术。所谓泛型技术,说白了就是试图用不变的代码来实现可变的法。比如:模板技术,RTTI技术,虚函数技术,要么是试囑ց到在~译时决议,要么试图做到q行时决议?

关于虚函数的使用Ҏ(gu)Q我在这里不做过多的阐述。大家可以看看相关的C++的书c。在q篇文章中,我只想从虚函数的实现机制上面为大?一个清晰的剖析?

当然Q相同的文章在网上也出现q一些了Q但我L觉这些文章不是很Ҏ(gu)阅读Q大D大D늚代码Q没有图片,没有详细的说明,没有比较Q没有D一反三。不利于学习和阅读,所以这是我惛_下这文章的原因。也希望大家多给我提意见?

a归正传,让我们一赯入虚函数的世界?

虚函数表

对C++ 了解的h都应该知道虚函数QVirtual FunctionQ是通过一张虚函数表(Virtual TableQ来实现的。简UCؓV-Table?在这个表中,L要一个类的虚函数的地址表,q张表解决了l承、覆盖的问题Q保证其容真实反应实际的函数。这P在有虚函数的cȝ实例中这个表被分配在?q个实例的内存中Q所以,当我们用父类的指针来操作一个子cȝ时候,q张虚函数表显得由为重要了Q它?yu)像一个地图一P指明了实际所应该调用的函数?

q里我们着重看一下这张虚函数表。在C++的标准规D明书中说刎ͼ~译器必需要保证虚函数表的指针存在于对象实例中最前面的位|(q是Z保证正确取到虚函数的偏移量)?q意味着我们通过对象实例的地址得到q张虚函数表Q然后就可以遍历其中函数指针Qƈ调用相应的函数?

听我扯了那么多,我可以感觉出来你现在可能比以前更加晕头{向了?没关p,下面是实际的例子,怿聪明的你一看就明白了?

假设我们有这L一个类Q?

class Base {

public:

virtual void f() { cout << "Base::f" << endl; }

virtual void g() { cout << "Base::g" << endl; }

virtual void h() { cout << "Base::h" << endl; }

};

按照上面的说法,我们可以通过Base的实例来得到虚函数表?下面是实际例E:

typedef void(*Fun)(void);

Base b;

Fun pFun = NULL;

cout << "虚函数表地址Q? << (int*)(&b) << endl;

cout << "虚函数表 ?W一个函数地址Q? << (int*)*(int*)(&b) << endl;

// Invoke the first virtual function

pFun = (Fun)*((int*)*(int*)(&b));

pFun();

实际q行l果如下Q?Windows XP+VS2003, Linux 2.6.22 + GCC 4.1.3)

虚函数表地址Q?012FED4

虚函数表 ?W一个函数地址Q?044F148

Base::f

通过q个CZQ我们可以看刎ͼ我们可以通过?amp;b转成int *Q取得虚函数表的地址Q然后,再次取址可以得到第一个虚函数的地址了,也就是Base::f()Q这在上面的E序中得C验证Q把int* 强制转成了函数指针)。通过q个CZQ我们就可以知道如果要调用Base::g()和Base::h()Q其代码如下Q?

(Fun)*((int*)*(int*)(&b)+0); // Base::f()

(Fun)*((int*)*(int*)(&b)+1); // Base::g()

(Fun)*((int*)*(int*)(&b)+2); // Base::h()

q个时候你应该懂了吧。什么?q是有点晕。也是,q样的代码看着太ؕ了。没问题Q让我画个图解释一下。如下所C:

注意Q在上面q个图中Q我在虚函数表的最后多加了一个结点,q是虚函数表的结束结点,像字符串的l束W?#8220;\0”一P其标志了虚函数表的结束。这个结束标志的值在不同的编译器下是不同的。在WinXP+VS2003下,q个值是NULL。而在Ubuntu 7.10 + Linux 2.6.22 + GCC 4.1.3下,q个值是如果1Q表C有下一个虚函数表,如果值是0Q表C是最后一个虚函数表?

下面Q我分别说?#8220;无覆?#8221;?#8220;有覆?#8221;时的虚函数表的样子。没有覆盖父cȝ虚函数是毫无意义的。我之所以要讲述没有覆盖的情况,主要目的是ؓ了给一个对比。在比较之下Q我们可以更加清楚地知道其内部的具体实现?

一般承(无虚函数覆盖Q?/h3>

下面Q再让我们来看看l承时的虚函数表是什么样的。假设有如下所C的一个承关p:

h意,在这个承关pMQ子cL有重载Q何父cȝ函数。那么,在派生类的实例中Q其虚函数表如下所C:

对于实例QDerive d; 的虚函数表如下:

我们可以看到下面几点Q?

1Q虚函数按照其声明顺序放于表中?

2Q父cȝ虚函数在子类的虚函数前面?

我相信聪明的你一定可以参考前面的那个E序Q来~写一D늨序来验证?

一般承(有虚函数覆盖Q?/h3>

覆盖父类的虚函数是很昄的事情,不然Q虚函数变得毫无意义。下面,我们来看一下,如果子类中有虚函数重载了父类的虚函数Q会是一个什么样子?假设Q我们有下面q样的一个承关pR?

Z让大家看到被l承q后的效果,在这个类的设计中Q我只覆盖了父类的一个函敎ͼf()。那么,对于zcȝ实例Q其虚函数表会是下面的一个样子:

我们从表中可以看C面几点,

1Q覆盖的f()函数被放C虚表中原来父c虚函数的位|?

2Q没有被覆盖的函C旧?

q样Q我们就可以看到对于下面q样的程序,

Base *b = new Derive();

b->f();

由b所指的内存中的虚函数表的f()的位|已l被Derive::f()函数地址所取代Q于是在实际调用发生Ӟ是Derive::f()被调用了。这实C多态?

多重l承Q无虚函数覆盖)

下面Q再让我们来看看多重l承中的情况Q假设有下面q样一个类的承关pR注意:子类q没有覆盖父cȝ函数?

对于子类实例中的虚函数表Q是下面q个样子Q?

我们可以看到Q?

1Q?每个父类都有自己的虚表?

2Q?子类的成员函数被攑ֈ了第一个父cȝ表中。(所谓的W一个父cL按照声明序来判断的Q?

q样做就是ؓ了解决不同的父类cd的指针指向同一个子cd例,而能够调用到实际的函数?

多重l承Q有虚函数覆盖)

下面我们再来看看Q如果发生虚函数覆盖的情c?

下图中,我们在子cM覆盖了父cȝf()函数?

下面是对于子cd例中的虚函数表的图:

我们可以看见Q三个父c虚函数表中的f()的位|被替换成了子类的函数指针。这P我们可以Q一静态类型的父类来指向子c,q调用子cȝf()了。如Q?

Derive d;

Base1 *b1 = &d;

Base2 *b2 = &d;

Base3 *b3 = &d;

b1->f(); //Derive::f()

b2->f(); //Derive::f()

b3->f(); //Derive::f()

b1->g(); //Base1::g()

b2->g(); //Base2::g()

b3->g(); //Base3::g()

安全?/h3>

每次写C++的文章,d不了要批判一下C++。这文章也不例外。通过上面的讲qͼ怿我们对虚函数表有一个比较细致的了解了。水可蝲舟,亦可覆舟。下面,让我们来看看我们可以用虚函数表来q点什么坏事吧?

一、通过父类型的指针讉K子类自己的虚函数

我们知道Q子cL有重载父cȝ虚函数是一件毫无意义的事情。因为多态也是要Z函数重蝲的。虽然在上面的图中我们可以看到Base1的虚表中有Derive的虚函数Q但我们Ҏ(gu)不可能用下面的语句来调用子cȝ自有虚函敎ͼ

Base1 *b1 = new Derive();

b1->f1(); //~译出错

M妄图使用父类指针惌用子cM?strong>未覆盖父cȝ成员函数的行为都会被~译器视为非法,所以,q样的程序根本无法编译通过。但在运行时Q我们可以通过指针的方式访问虚函数表来辑ֈq反C++语义的行为。(关于q方面的试Q通过阅读后面附录的代码,怿你可以做到这一点)

二、访问non-public的虚函数

另外Q如果父cȝ虚函数是private或是protected的,但这些非public的虚函数同样会存在于虚函数表中,所以,我们同样可以使用讉K虚函数表的方式来讉Kq些non-public的虚函数Q这是很Ҏ(gu)做到的?

如:

class Base {

private:

virtual void f() { cout << "Base::f" << endl; }

};

class Derive : public Base{

};

typedef void(*Fun)(void);

void main() {

Derive d;

Fun pFun = (Fun)*((int*)*(int*)(&d)+0);

pFun();

}

l束?/h3>

C++q门语言是一门Magic的语aQ对于程序员来说Q我们似乎永q摸不清楚这门语a背着我们在干了什么。需要熟(zhn)这门语aQ我们就必需要了解C++里面的那些东西,需要去了解C++中那些危险的东西。不Ӟq是一U搬L头砸自己脚的~程语言?/p>



大v 2008-09-18 18:54 发表评论
]]> ɫ͵͵88ŷƷþþ| Ʒþ8xѹۿ| ƷþþþþӰԺ| þˬˬˬ| Ʒ˾þþ| þþþþþþ66ƷƬ| ˾þô߽Ʒ| þü޾Ʒ?V| Ʒþþþþ˳ | ˾þô߽| ŷպۺϾþ | þ99ֻƵƷ6| þĻƷһ| Ļþһ| ɫɫۺϾþҹҹ| ձǿƬþþþþAAA | þþƷavպ| þþþþAv뾫Ʒר| þþƷAV鶹 | þ㽶߿ۿ| 91þþƷƵ| þǿdŮվ| Ʒþþþþ| Ʒ˾þþþӰԺ| þۺ¶þü| պ뾫Ʒþһ | þݺҹҹav˳| þþþþùaѹۿɫƬ| ۺ˾þôý| ޳ɫ999þվ| ޹˾þۺ| ƷŮþþm| ŷСþþþþþ | þ붯aëƬ| þþ91Ʒһ| þݺҹҹ2020| þ99ƷСѼ | þùֱ| þ㽶97Ʒ| ձɫվWWWþ | ݺɫþۺ |