﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-Mato is No.1-随笔分类-字符串匹配</title><link>http://www.cppblog.com/MatoNo1/category/16633.html</link><description>Mato是一只超级大沙茶……但他一直以来都想成为各项比赛都No.1的神犇……</description><language>zh-cn</language><lastBuildDate>Wed, 24 Oct 2012 12:28:27 GMT</lastBuildDate><pubDate>Wed, 24 Oct 2012 12:28:27 GMT</pubDate><ttl>60</ttl><item><title>【AHOI2013复仇】SCOI2003 字符串折叠 </title><link>http://www.cppblog.com/MatoNo1/archive/2012/10/24/193781.html</link><dc:creator>Mato_No1</dc:creator><author>Mato_No1</author><pubDate>Wed, 24 Oct 2012 07:11:00 GMT</pubDate><guid>http://www.cppblog.com/MatoNo1/archive/2012/10/24/193781.html</guid><wfw:comment>http://www.cppblog.com/MatoNo1/comments/193781.html</wfw:comment><comments>http://www.cppblog.com/MatoNo1/archive/2012/10/24/193781.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MatoNo1/comments/commentRss/193781.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MatoNo1/services/trackbacks/193781.html</trackback:ping><description><![CDATA[<a title="原题地址" href="http://www.lydsy.com/JudgeOnline/problem.php?id=1090">原题地址</a><br />本沙茶在2009年1月曾经在<a title="RQNOJ上" href="http://www.rqnoj.cn/Problem_275.html">RQNOJ上</a>捉过这题，那时候是很难的题，现在就很水了囧&#8230;&#8230;（当然，本沙茶那个时候不会exKMP，是用暴力的，可是时间复杂度仍能是O(N<sup>3</sup>)）。<br /><br />F[i][j]=min{F[i][k]+F[k+1][j]，min{((j-i+1)/(k-i+1)的十进制位数)+2+F[i][k]，<strong><span style="color: red">k-i+1</span></strong>}, i&lt;=k&lt;j，第二项需要满足原字符串[i..j]这一段恰好由[i..k]这一段的若干次复制得到}<br />（加上k-i+1是因为对于以下三种重叠字符串，不压缩比压缩要短：AA型、AAA型、ABAB型）<br />边界：F[i][i]=1；<br /><br />问题是在上述方程的第二项里如何求出可行的k。显然，只需要对[i..j]这一段作exKMP，求出nx，然后k可行当且仅当满足：（1）nx[k+1]=j-k；（2）(k-i+1)|(j-i+1)；<br /><br />不过，本题在写exKMP的过程中会出现很囧的问题&#8230;&#8230;由于下标不是从0开始，而是从i开始，所以很多地方关于下标的计算都要改掉，非常不方便，而且很容易疵掉。与其这样，还不如把[i..j]这一段复制到一个新字符串里，下标从0开始。对于其它的某些字符串算法和数据结构，或许也是这样囧&#8230;&#8230;<br /><br />代码：<br />
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><span style="color: #000000">#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">iostream</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">stdio.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">stdlib.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">string</span><span style="color: #000000">.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br /></span><span style="color: #0000ff">using</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">namespace</span><span style="color: #000000">&nbsp;std;<br /></span><span style="color: #0000ff">#define</span><span style="color: #000000">&nbsp;re(i,&nbsp;n)&nbsp;for&nbsp;(int&nbsp;i=0;&nbsp;i&lt;n;&nbsp;i++)</span><span style="color: #000000"><br /></span><span style="color: #0000ff">#define</span><span style="color: #000000">&nbsp;re1(i,&nbsp;n)&nbsp;for&nbsp;(int&nbsp;i=1;&nbsp;i&lt;=n;&nbsp;i++)</span><span style="color: #000000"><br /></span><span style="color: #0000ff">#define</span><span style="color: #000000">&nbsp;re2(i,&nbsp;l,&nbsp;r)&nbsp;for&nbsp;(int&nbsp;i=l;&nbsp;i&lt;r;&nbsp;i++)</span><span style="color: #000000"><br /></span><span style="color: #0000ff">#define</span><span style="color: #000000">&nbsp;re3(i,&nbsp;l,&nbsp;r)&nbsp;for&nbsp;(int&nbsp;i=l;&nbsp;i&lt;=r;&nbsp;i++)</span><span style="color: #000000"><br /></span><span style="color: #0000ff">#define</span><span style="color: #000000">&nbsp;rre(i,&nbsp;n)&nbsp;for&nbsp;(int&nbsp;i=n-1;&nbsp;i&gt;=0;&nbsp;i--)</span><span style="color: #000000"><br /></span><span style="color: #0000ff">#define</span><span style="color: #000000">&nbsp;rre1(i,&nbsp;n)&nbsp;for&nbsp;(int&nbsp;i=n;&nbsp;i&gt;0;&nbsp;i--)</span><span style="color: #000000"><br /></span><span style="color: #0000ff">#define</span><span style="color: #000000">&nbsp;rre2(i,&nbsp;r,&nbsp;l)&nbsp;for&nbsp;(int&nbsp;i=r-1;&nbsp;i&gt;=l;&nbsp;i--)</span><span style="color: #000000"><br /></span><span style="color: #0000ff">#define</span><span style="color: #000000">&nbsp;rre3(i,&nbsp;r,&nbsp;l)&nbsp;for&nbsp;(int&nbsp;i=r;&nbsp;i&gt;=l;&nbsp;i--)</span><span style="color: #000000"><br /></span><span style="color: #0000ff">#define</span><span style="color: #000000">&nbsp;ll&nbsp;long&nbsp;long</span><span style="color: #000000"><br /></span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;MAXN&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">110</span><span style="color: #000000">,&nbsp;INF&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">~</span><span style="color: #000000">0U</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&gt;&gt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">2</span><span style="color: #000000">;<br /></span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;n,&nbsp;F[MAXN][MAXN],&nbsp;nx[MAXN],&nbsp;res;<br /></span><span style="color: #0000ff">char</span><span style="color: #000000">&nbsp;ss[MAXN&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">],&nbsp;ss0[MAXN&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">];<br /></span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;init()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;scanf(</span><span style="color: #000000">"</span><span style="color: #000000">%s</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;ss);&nbsp;n&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;strlen(ss);<br />}<br /></span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;sol0(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;l,&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;r)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;W&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;r&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;l&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">;&nbsp;re3(i,&nbsp;l,&nbsp;r)&nbsp;ss0[i&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;l]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;ss[i];<br />&nbsp;&nbsp;&nbsp;&nbsp;nx[</span><span style="color: #000000">0</span><span style="color: #000000">]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;W;&nbsp;nx[</span><span style="color: #000000">1</span><span style="color: #000000">]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;nx[</span><span style="color: #000000">0</span><span style="color: #000000">]&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">;&nbsp;re(i,&nbsp;W)&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(ss0[i]&nbsp;</span><span style="color: #000000">!=</span><span style="color: #000000">&nbsp;ss0[i&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">])&nbsp;{nx[</span><span style="color: #000000">1</span><span style="color: #000000">]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;i;&nbsp;</span><span style="color: #0000ff">break</span><span style="color: #000000">;}<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;k&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;len,&nbsp;p&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;k&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;nx[k]&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;x,&nbsp;y;<br />&nbsp;&nbsp;&nbsp;&nbsp;re2(i,&nbsp;</span><span style="color: #000000">2</span><span style="color: #000000">,&nbsp;W)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;len&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;nx[i&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;k];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(i&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;len&nbsp;</span><span style="color: #000000">&lt;=</span><span style="color: #000000">&nbsp;p)&nbsp;nx[i]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;len;&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;p&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">;&nbsp;y&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;p&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;i&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(y&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">)&nbsp;{x</span><span style="color: #000000">++</span><span style="color: #000000">;&nbsp;y&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">for</span><span style="color: #000000">&nbsp;(;&nbsp;x</span><span style="color: #000000">&lt;=</span><span style="color: #000000">W&nbsp;</span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000">&nbsp;ss0[x]</span><span style="color: #000000">==</span><span style="color: #000000">ss0[y];&nbsp;x</span><span style="color: #000000">++</span><span style="color: #000000">,&nbsp;y</span><span style="color: #000000">++</span><span style="color: #000000">)&nbsp;;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nx[i]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;y;&nbsp;k&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;i;&nbsp;p&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;i&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;y&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;res0&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;INF,&nbsp;tmp,&nbsp;V;<br />&nbsp;&nbsp;&nbsp;&nbsp;re2(i,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;W)&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(</span><span style="color: #000000">!</span><span style="color: #000000">(W&nbsp;</span><span style="color: #000000">%</span><span style="color: #000000">&nbsp;i)&nbsp;</span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000">&nbsp;nx[i]&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;W&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;i)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;V&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;F[l][l&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;i&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">]&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">2</span><span style="color: #000000">;&nbsp;tmp&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;W&nbsp;</span><span style="color: #000000">/</span><span style="color: #000000">&nbsp;i;&nbsp;</span><span style="color: #0000ff">while</span><span style="color: #000000">&nbsp;(tmp)&nbsp;{tmp&nbsp;</span><span style="color: #000000">/=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">10</span><span style="color: #000000">;&nbsp;V</span><span style="color: #000000">++</span><span style="color: #000000">;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(W&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;V)&nbsp;V&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;W;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(V&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;res0)&nbsp;res0&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;V;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;res0;<br />}<br /></span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;solve()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;re(i,&nbsp;n)&nbsp;F[i][i]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;j,&nbsp;tmp;<br />&nbsp;&nbsp;&nbsp;&nbsp;re2(x,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;n)&nbsp;re(i,&nbsp;n</span><span style="color: #000000">-</span><span style="color: #000000">x)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;j&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;i&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;x;&nbsp;F[i][j]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;sol0(i,&nbsp;j);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;re2(k,&nbsp;i,&nbsp;j)&nbsp;{tmp&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;F[i][k]&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;F[k&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">][j];&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(tmp&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;F[i][j])&nbsp;F[i][j]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;tmp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;res&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;F[</span><span style="color: #000000">0</span><span style="color: #000000">][n&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">];<br />}<br /></span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;pri()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="color: #000000">"</span><span style="color: #000000">%d\n</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;res);<br />}<br /></span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;main()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;init();<br />&nbsp;&nbsp;&nbsp;&nbsp;solve();<br />&nbsp;&nbsp;&nbsp;&nbsp;pri();<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />}<br /></span></div><img src ="http://www.cppblog.com/MatoNo1/aggbug/193781.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MatoNo1/" target="_blank">Mato_No1</a> 2012-10-24 15:11 <a href="http://www.cppblog.com/MatoNo1/archive/2012/10/24/193781.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>COCI 2011～2012 #5 后两题题解</title><link>http://www.cppblog.com/MatoNo1/archive/2012/04/18/171899.html</link><dc:creator>Mato_No1</dc:creator><author>Mato_No1</author><pubDate>Wed, 18 Apr 2012 12:26:00 GMT</pubDate><guid>http://www.cppblog.com/MatoNo1/archive/2012/04/18/171899.html</guid><wfw:comment>http://www.cppblog.com/MatoNo1/comments/171899.html</wfw:comment><comments>http://www.cppblog.com/MatoNo1/archive/2012/04/18/171899.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MatoNo1/comments/commentRss/171899.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MatoNo1/services/trackbacks/171899.html</trackback:ping><description><![CDATA[<a title="相关链接" href="http://www.cppblog.com/MatoNo1/archive/2012/03/18/168229.html">相关链接</a><br />今天在回顾以前的题目的时候，秃然发现COCI 2011～2012 #5的后两题并非神犇题（至少一般人可以捉的）&#8230;&#8230;是我当时想傻掉了囧&#8230;&#8230;<br /><br />blokovi：<br />首先很容易发现最优方案必然是从顶到底，先尽量往右边放，放到某一个转折点处再尽量往左边放&#8230;&#8230;<br />然后就是枚举这个转折点，乱算一下就行了，暴力O(N<sup>2</sup>)的可以过7个点（本沙茶现场赛时就是用这个的）&#8230;&#8230;<br />优化：可以从上到下依次枚举转折点，设目前的转折点为i，则在下一次枚举时（(i+1)为转折点），把(i+1)往右平移2单位，然后根据那个重心计算公式可以得出，第(i+2)个及以后的必然是整体向右平移(2*m2)/(m1+m2)，其中m1为前i个的质量和，m2为第(i+1)个的质量&#8230;&#8230;在此基础上维护转折点前重心位置、转折点的重心的横坐标（相对于最上面的那个）以及最下面的那个的重心的横坐标（相对于最上面的那个）就行了（注意转折点是第一个或最后一个的特殊情况要单独处理），时间复杂度O(N)。<br /><br />poplocavanje：<br />其实这题只要用AC自动机随便乱搞一下就行了&#8230;&#8230;Trie上的每个结点维护一个KK，表示该结点所代表的字符串的后缀的最大匹配长度（当然前提条件是该结点是危险的），则：（1）若该结点本来就代表一个待匹配的子串，则KK值为子串长度；（2）若该结点是通过失败指针上溯到一个危险结点的，则该结点的KK就是上溯到的那个危险结点的KK。然后做一次匹配，记下所有的匹配区间，再求出未被区间覆盖的总长度（排序+扫描即可，不需任何数据结构）就行了。<br /><br />注意几个易疵的地方：<br />（1）Trie的大小要开到4M才能过（不过再大就要MLE了囧&#8230;&#8230;）；<br />（2）在建自动机计算KK的时候，如果一个结点本来就是危险的（即上述第1种结点），此过程中又发现它是上述第2种结点，则<strong><span style="color: #ff0000;">不</span><span style="color: red;">能重新计算KK</span></strong>；<br />（3）最后求未被区间覆盖总长度的方法：先记下所有的区间，按照先左端点递增序后右端点递增序排序，当中去掉被别的区间覆盖的区间，然后先看一下排序后的第一个区间和最后一个区间，得出第一个区间之前与最后一个区间之后的未被覆盖的部分，中间的扫描求解时，如果某区间的左端点大于(前一区间的右端点+1)，则计入中间的空当&#8230;&#8230;不过还有一种方法就是不去掉被别的覆盖的区间，而是在扫描过程中维护右端点最大值maxr，然后把上面方法中的所有右端点改为maxr即可。<br /><br />代码：<br /><a title="blokovi" href="http://ideone.com/APoKA">blokovi</a> <a title="poplocavanje" href="http://ideone.com/aWQ8O">poplocavanje</a><img src ="http://www.cppblog.com/MatoNo1/aggbug/171899.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MatoNo1/" target="_blank">Mato_No1</a> 2012-04-18 20:26 <a href="http://www.cppblog.com/MatoNo1/archive/2012/04/18/171899.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>KMP、AC自动机在字符串匹配类动态规划问题中的应用</title><link>http://www.cppblog.com/MatoNo1/archive/2011/10/30/159339.html</link><dc:creator>Mato_No1</dc:creator><author>Mato_No1</author><pubDate>Sun, 30 Oct 2011 03:22:00 GMT</pubDate><guid>http://www.cppblog.com/MatoNo1/archive/2011/10/30/159339.html</guid><wfw:comment>http://www.cppblog.com/MatoNo1/comments/159339.html</wfw:comment><comments>http://www.cppblog.com/MatoNo1/archive/2011/10/30/159339.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MatoNo1/comments/commentRss/159339.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MatoNo1/services/trackbacks/159339.html</trackback:ping><description><![CDATA[有一类动态规划（其中也包含递推）问题，要求满足一些限制条件的字符串，这些限制条件是&#8220;需要含有某个子串&#8221;或&#8220;不能含有某个子串&#8221;，那么KMP、AC自动机等就有大用了。<br /><br />【例1】<a title="HDU3689" href="http://acm.hdu.edu.cn/showproblem.php?pid=3689">HDU3689</a><br />题意：字符集中有一些字符，给出每个字符的出现概率（它们的和保证为1），再给出一个子串B，求：任给一个长度为N的字符串A（只能包含字符集中的字符），使得S是A的子串的概率。<br /><br />求解这类问题首先要进行补集转化。因为子串可能有重叠（比如"ababa"中就出现了两个"aba"），所以先转化为&#8220;求任给一个长度为N的字符串A（只能包含字符集中的字符），使得<span style="color: red"><strong>B不是A的子串</strong></span>的概率&#8221;，然后再用1减去这个概率即为结果。<br />设F[i][j]为&#8220;在所有长度为i的<span style="color: red"><strong>不出现B</strong></span>的字符串中，后缀与B的前缀匹配长度为j（即该字符串的后缀与B的前缀的<span style="color: red"><strong>最大</strong></span>匹配长度为j）的概率&#8221;，很显然，F是由递推得到了，关键是如何进行状态转移？或者说，在递推过程中，哪些状态可能成为F[i][j]的前趋状态？<br />假设F[i-1][k]是F[i][j]的前趋状态，也就是说，<span style="color: red"><strong>在字符集中至少存在一个字符c，使得主串的第i位（最后一位）取c时，能够从F[i-1][k]转移到F[i][j]</strong></span>。这就需要求一个值S[k][c]，表示当主串的后缀与B的前缀的（最大）匹配长度为k时，在主串后再加上一个字符c，其匹配长度会变成什么。举例：设目前主串A'="abasab"，B="asabs"，其匹配长度为4，若在A'后加上一个字符's'，则匹配长度变为5，所以S[4]['s']=5，而若在A'后加上一个字符'a'，则匹配长度会变成1，所以S[4]['a']=1。显然S值和A前面的哪些字符是没有关系的。<br />那么这个S值如何计算？其实可以发现，S和KMP算法中的nx数组神似，因此完全可以按照计算nx数组的办法来计算S。具体来说，先要对B作KMP自身匹配，求出其nx数组，然后，在求S[k][c]的时候，尝试在B的第k位（由于B的下标从0开始所以B[k-1]）后加上字符c，看看会&#8220;回退&#8221;到哪里即可。代码： 
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;j&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;&nbsp;nx[</span><span style="color: #000000">0</span><span style="color: #000000">]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;re2(i,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;m)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">while</span><span style="color: #000000">&nbsp;(j&nbsp;</span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000">&nbsp;A[i]&nbsp;</span><span style="color: #000000">!=</span><span style="color: #000000">&nbsp;A[j])&nbsp;j&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;nx[j&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(A[i]&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;A[j])&nbsp;j</span><span style="color: #000000">++</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nx[i]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;j;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;re(i,&nbsp;m)&nbsp;re(k,&nbsp;SZ)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;j&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;i;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">while</span><span style="color: #000000">&nbsp;(j&nbsp;</span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000">&nbsp;A[j]&nbsp;</span><span style="color: #000000">!=</span><span style="color: #000000">&nbsp;k&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">97</span><span style="color: #000000">)&nbsp;j&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;nx[j&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(A[j]&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;k&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">97</span><span style="color: #000000">)&nbsp;S[i][k]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">++</span><span style="color: #000000">j;&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;S[i][k]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>这里m是B的长度。注意，当i=m时，S[i][j]是无意义的，因为前面已经说过了不能出现B。<br />在求出S值后就能求出F值了。对于状态F[i][j]，若存在一个字符c使得x=S[i][c]（满足0&lt;=x&lt;m），则F[i][j]是F[i+1][x]的前趋状态。当然，由于本题是求概率而不是求总数，且每个字符出现的概率还不一样，所以转移的时候，应是将F[i+1][x]加上F[i][j]*P[c]（P[c]是字符c出现的概率），边界：F[0][0]=1，F[0][1..m-1]均为0。<br />最终结果为1-&#8721;F[N][0..m-1]。<br /><br /><a title="代码" href="http://www.ideone.com/CDcNk">代码</a><br /><br />【例2】<a title="PKU1625" href="http://poj.org/problem?id=1625">PKU1625</a>（<a title="URAL1158" href="http://acm.timus.ru/problem.aspx?space=1&amp;num=1158">URAL1158</a>）<br />题意：给出一些子串，求长度为N，各个字符都属于给定的字符集的所有字符串中，不包含任何一个给出的子串的字符串个数（需要使用压9位的高精度）。<br /><br />本题显然是【例1】的多子串形式，而用来解决多个字符串同时匹配的只有AC自动机，那么如何在本题中使用AC自动机求解呢？<br />观察【例1】中的F[i][j]，可以想象一下，一个图中有m个顶点，分别表示匹配长度为0..(m-1)，然后不断新加入的字符让这些状态在这些结点间不断转移（状态转移就是图中的边），这样，F[i][<span>j]就表示&#8220;阶段i到达结点j上&#8221;。而AC自动</span><span>机是基于Trie（树）的，</span><span>其中有现成</span><span>的结</span><span>点，这就揭示了本题的状</span><span>态</span><span><strong>：</strong></span><br /><span>F[i][j]</span><span>表</span><span>示</span><strong><span style="color: #ff0000">长度为i的合法的字符串（就是满足字符集限制且不包含任何一个给定子串）中，在匹配到最后一位（</span></strong><strong style="color: #ff0000">第i位）后，刚好到达结点j的字符串的</strong><strong style="color: #ff0000">个数</strong>。<br />同样，S[k][c]表示&#8220;目前到达结点k，接下来的一个字符是c的时候，会到达哪个结点。在对所有的子串建立了自动机之后，S值只要类似地搞就能求出来了。然后F的转移也就搞定了。<br />不过，本题要万分注意AC自动机的一个BUG：在建立了自动机以后，需要把所有本身不危险（如果一个结点代表的字符串刚好是某一个给出的不能出现的子串，则该结点是危险结点），但通过失败指针不断上溯能够到达一个危险结点的结点，也标记为危险结点，比如两个子串是"abcde"和"bc"，则代表"abcd"的那个结点由于包含了"bc"所以也是危险的。<br />此外，本题的输入要注意，字符集的ASCII码范围是-128~127，所以必须用char而不是unsigned char，且由于可能包含空格所以必须用gets()而不是scanf()输入，又因为C/C++中木有负数下标，因此在输入之后还要转化一下（加128）。<br /><br /><a title="代码" href="http://www.ideone.com/MHp6H">代码</a><br /><br />【例3】<a title="PKU3691" href="http://poj.org/problem?id=3691">PKU3691</a><br />题意：给出一些子串和一个字符串A（其每个字符均属于字符集{'A', 'C', 'G', 'T'}），求至少要改动A的几个字符（不能改成不属于字符集的字符），使得它不包含任何一个给出的子串，若不管怎么改都不行，则结果为-1。<br /><br />这就是真正的DP了。设F[i][j]为前i位，到达的结点为j，最少改动的字符个数，则转移方程为<br />F[i][j] = min{F[i-1][x] + (A[i] != c)}，c&#8712;{'A', 'C', 'G', 'T'}，S[x][c]=j。边界：F[0][root]=0，其余的F[0][]=+&#8734;，A的实际下标从1开始。<br />求S数组的方法见【例2】<br /><br /><a title="代码" href="http://www.ideone.com/JrEIY">代码</a><br /><br />【例4】<a title="PKU3208" href="http://poj.org/problem?id=3208">PKU3208</a><br />题意：含有连续的三个数字6的正整数，称为"beastly number"，求第P个（1&lt;=P&lt;=50000000）"beastly number"（其位数不会超过15位）。<br />（这题是本沙茶在PKU上至今为止，自己想出算法的AC人数最少的题）<br />本题其实是用不着KMP的，因为"666"这样简单的子串&#8230;&#8230;<br /><br />思路：由于位数不会超过15位（后来发现最多只有10位），所以每个"beastly number"都可以看成一个长度为15，字符集为['0'..'9']的字符串（注意是可以有前导0的，因为位数可能不足15位）A，整个过程也就是从高位（第0位）向低位（第14位）求出A的各位。<br /><br />预处理：求出F[i][j]，表示若A的前i位已经确定（其中不含"666"，准确来说是非末尾不含"666"），且前i位的末尾刚好有j个'6'（j的范围是0到3）时，有多少个"beastly number"（注意，前i位既然已经确定，就不可更改了，能够决定的只有第i位的后面）。<br />显然先要求出F0[i][j]表示有多少个不是"beastly number"。其递推方程不好写，见代码（其实也是很好理解的）。然后F[i][j]=10<sup>14-i</sup> - F0[i][j]。<br /><br />然后就是不断调整边界来构造了。准确来说，设前i-1位已经确定，现在要确定第i位，则枚举第i位是0~9中的哪个值，然后求出满足条件的最小的"beastly number"和最大的"beastly number"的名次（注意，名次是从1开始的），看看P在不在其中，这样就能确定了。严重注意：如果已确定的位数中已经出现了"666"，接下来的就不用枚举了，直接在后面接上P-L就行了，L为左边界。<br /><br />但是，为什么要把本题放在KMP的专题里面呢囧？<span>因为如果这个子串不是"666"而是一些结构复</span><span>杂的东东比如"123131"这样的，只有借助K</span><span>MP算法了。这时，F[i][j]就表示 A的前i位已经确定（非末尾不含这个子串），且其后缀与这个子串的前缀匹</span><span>配长度为</span><span>j，</span>有多少个"beastly number" ，转移方程与前几个例子类似。<br /><br /><a title="代码" href="http://www.ideone.com/Areon">代码</a><br /><br />总结：<br />KMP算法和AC自动机的状态转移性质决定了它们在字符串匹配类DP问题中的巨大作用。在实际应用中，要注意灵活使用它们。此外，AC自动机的那个BUG是一定要注意的。 <img src ="http://www.cppblog.com/MatoNo1/aggbug/159339.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MatoNo1/" target="_blank">Mato_No1</a> 2011-10-30 11:22 <a href="http://www.cppblog.com/MatoNo1/archive/2011/10/30/159339.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>后缀数组</title><link>http://www.cppblog.com/MatoNo1/archive/2011/10/23/158926.html</link><dc:creator>Mato_No1</dc:creator><author>Mato_No1</author><pubDate>Sun, 23 Oct 2011 08:51:00 GMT</pubDate><guid>http://www.cppblog.com/MatoNo1/archive/2011/10/23/158926.html</guid><wfw:comment>http://www.cppblog.com/MatoNo1/comments/158926.html</wfw:comment><comments>http://www.cppblog.com/MatoNo1/archive/2011/10/23/158926.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/MatoNo1/comments/commentRss/158926.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MatoNo1/services/trackbacks/158926.html</trackback:ping><description><![CDATA[【后缀数组真难懂啊啊&#8230;&#8230;就20+行的代码搞了几天才理解&#8230;&#8230;不知是不是我太沙茶了】<br /><br />【1】一些定义：<br />字符串：广义的字符串是指&#8220;元素类型有序，且元素值有一定范围的序列&#8221;，其元素不一定非要是字符，可以是数字等，因此整数、二进制数等也是字符串；<br />字符集：字符串的元素值的范围称为字符集，其大小记为SZ。<br />字符串的长度：字符串中元素的个数，一般记为N，长度为N的字符串A第一次提到时一般用A[0..N-1]来表示；<br />前缀：字符串A[0..N-1]的从A[0]开始的若干个连续的字符组成的字符串称为A的前缀，以下&#8220;前缀i&#8221;或者&#8220;编号为i的前缀&#8221;指的都是A[0..i]；<br />后缀：字符串A[0..N-1]的到A[N-1]终止的若干个连续的字符组成的字符串称为A的后缀，以下&#8220;后缀i&#8221;或者&#8220;编号为i的后缀&#8221;指的都是A[i..N-1];<br /><br />对于一个长度为N的字符串，将其N个后缀按字典序大小进行排序，得到两个数组sa[i]和rank[i]，sa[i]为排在第i位的后缀的编号（也就是一般说的ord[i]），rank[i]为排在后缀i排在的位置（称为后缀i的名次）。sa、rank值的范围均为[0..N-1]。sa和rank互逆，即sa[i]=j等价于rank[j]=i，或者说成sa[rank[i]]=rank[sa[i]]=i。这里，sa称为<span style="color: #ff0000"><strong>后缀数组</strong></span>，rank称为<span style="color: #ff0000"><strong>名次数组</strong></span>。<br /><br />【2】用倍增算法求后缀数组：<br />在论文里，后缀数组有两种求法：倍增算法和DC3算法，前者的时间复杂度为O(NlogN)，但常数较小，后者的时间复杂度为O(N)，但常数较大，在实际应用中，两者的总时间相差不大，且后者比前者难理解得多（本沙茶理解前者都用了几天时间&#8230;&#8230;后者就木敢看了）。这里就总结一下倍增算法吧囧&#8230;&#8230;<br />首先，贴一下本沙茶的用倍增算法求后缀数组的模板： 
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;suffix_array()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;p,&nbsp;v0,&nbsp;v1,&nbsp;v00,&nbsp;v01;<br />&nbsp;&nbsp;&nbsp;&nbsp;re(i,&nbsp;SZ)&nbsp;S[i]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;re(i,&nbsp;n)&nbsp;rank[i]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;A[i];<br />&nbsp;&nbsp;&nbsp;&nbsp;re(i,&nbsp;n)&nbsp;S[A[i]]</span><span style="color: #000000">++</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;re2(i,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;SZ)&nbsp;S[i]&nbsp;</span><span style="color: #000000">+=</span><span style="color: #000000">&nbsp;S[i&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">];<br />&nbsp;&nbsp;&nbsp;&nbsp;rre(i,&nbsp;n)&nbsp;sa[</span><span style="color: #000000">--</span><span style="color: #000000">S[A[i]]]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;i;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">for</span><span style="color: #000000">&nbsp;(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;j</span><span style="color: #000000">=</span><span style="color: #000000">1</span><span style="color: #000000">;&nbsp;j</span><span style="color: #000000">&lt;</span><span style="color: #000000">n;&nbsp;j</span><span style="color: #000000">&lt;&lt;=</span><span style="color: #000000">1</span><span style="color: #000000">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;&nbsp;re2(i,&nbsp;n</span><span style="color: #000000">-</span><span style="color: #000000">j,&nbsp;n)&nbsp;tmp[p</span><span style="color: #000000">++</span><span style="color: #000000">]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;i;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;re(i,&nbsp;n)&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(sa[i]&nbsp;</span><span style="color: #000000">&gt;=</span><span style="color: #000000">&nbsp;j)&nbsp;tmp[p</span><span style="color: #000000">++</span><span style="color: #000000">]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;sa[i]&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;j;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;re(i,&nbsp;SZ)&nbsp;S[i]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;re(i,&nbsp;n)&nbsp;S[rank[i]]</span><span style="color: #000000">++</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;re2(i,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;SZ)&nbsp;S[i]&nbsp;</span><span style="color: #000000">+=</span><span style="color: #000000">&nbsp;S[i&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rre(i,&nbsp;n)&nbsp;sa[</span><span style="color: #000000">--</span><span style="color: #000000">S[rank[tmp[i]]]]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;tmp[i];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tmp[sa[</span><span style="color: #000000">0</span><span style="color: #000000">]]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;p&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;re2(i,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;n)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v0&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;sa[i&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">];&nbsp;v1&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;sa[i];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(v0&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;j&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;n)&nbsp;v00&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;rank[v0&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;j];&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;v00&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(v1&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;j&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;n)&nbsp;v01&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;rank[v1&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;j];&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;v01&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(rank[v0]&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;rank[v1]&nbsp;</span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000">&nbsp;v00&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;v01)&nbsp;tmp[sa[i]]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;p;&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;tmp[sa[i]]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">++</span><span style="color: #000000">p;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;re(i,&nbsp;n)&nbsp;rank[i]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;tmp[i];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SZ&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">++</span><span style="color: #000000">p;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /></span></div>这里A是待求sa和rank的字符串。<br /><br />&lt;1&gt;倍增算法的思想：<br />记R[i][j]为A[i..i+2<sup>j</sup>-1]（如果越界，则后面用@填充）在A的所有长度为2<sup>j</sup>的子串（越界则后面用@填充）中的名次（rank）值。倍增算法就是按阶段求出所有R[i][j]的值，直到2<sup>j</sup>&gt;N为止。首先，R[i][0]的就是字符A[i]在A[0..N-1]中的名次，是可以直接用计数排序来实现的。然后，若R[0..N-1][j-1]已知，则可以按照以下方法求出R[0..N-1][j]的值：对每个i（0&lt;=i&lt;N），构造一个二元组&lt;X<sub>i</sub>, Y<sub>i</sub>&gt;，其中X<sub>i</sub>=R[i][j-1]，Y<sub>i</sub>=R[i+2<sup>j</sup>][j-1]（若i+2<sup>j</sup>&gt;=N，则Y<sub>i</sub>=-&#8734;），然后对这N个二元组按照第一关键字为X，第二关键字为Y（若两者都相等则判定为相等）进行排序（可以用基数排序来实现），排序后，&lt;X<sub>i</sub>, Y<sub>i</sub>&gt;的名次就是的R[i][j]的值。<br /><br />&lt;2&gt;一开始，对A中的各个字符进行计数排序：
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000">re(i,&nbsp;SZ)&nbsp;S[i]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />re(i,&nbsp;n)&nbsp;rank[i]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;A[i];<br />re(i,&nbsp;n)&nbsp;S[A[i]]</span><span style="color: #000000">++</span><span style="color: #000000">;<br />re2(i,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;SZ)&nbsp;S[i]&nbsp;</span><span style="color: #000000">+=</span><span style="color: #000000">&nbsp;S[i&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">];<br />rre(i,&nbsp;n)&nbsp;sa[</span><span style="color: #000000">--</span><span style="color: #000000">S[A[i]]]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;i;<br /></span></div>这个木有神马好说的，在搞懂了基数排序之后可以秒掉。唯一不同的是这里加了一句：rank[i]=A[i]，这里的rank[i]是初始的i的名次，MS不符合rank[i]的定义和sa与rank间的互逆性。这里就要解释一下了囧。因为在求sa的过程中，rank值可能不符合定义，因为长度为2<sup>j</sup>的子串可能会有相等的，此时它们的rank值也要相等，而sa值由于有下标的限制所以不可能有相等的。因此，在过程中，rank其实是用来代替A的子串的，这样rank值只需要表示一个&#8220;相对顺序&#8221;就行了，也就是：rank[i0]&gt;(=, &lt;)rank[i1]，当且仅当A[i0..i0+2<sup>j</sup>-1]&gt;(=, &lt;)A[i1..i1+2<sup>j</sup>-1]。这样，可以直接将A[i]值作为初始的rank[i]值。<br /><br />&lt;3&gt;j（代替2<sup>j</sup>）的值从1开始不断倍增，对二元组进行基数排序求出新阶段的sa值：<br />
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000ff">for</span><span style="color: #000000">&nbsp;(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;j</span><span style="color: #000000">=</span><span style="color: #000000">1</span><span style="color: #000000">;&nbsp;j</span><span style="color: #000000">&lt;</span><span style="color: #000000">n;&nbsp;j</span><span style="color: #000000">&lt;&lt;=</span><span style="color: #000000">1</span><span style="color: #000000">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;&nbsp;re2(i,&nbsp;n</span><span style="color: #000000">-</span><span style="color: #000000">j,&nbsp;n)&nbsp;tmp[p</span><span style="color: #000000">++</span><span style="color: #000000">]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;i;<br />&nbsp;&nbsp;&nbsp;&nbsp;re(i,&nbsp;n)&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(sa[i]&nbsp;</span><span style="color: #000000">&gt;=</span><span style="color: #000000">&nbsp;j)&nbsp;tmp[p</span><span style="color: #000000">++</span><span style="color: #000000">]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;sa[i]&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;j;<br />&nbsp;&nbsp;&nbsp;&nbsp;re(i,&nbsp;SZ)&nbsp;S[i]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;re(i,&nbsp;n)&nbsp;S[rank[i]]</span><span style="color: #000000">++</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;re2(i,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;SZ)&nbsp;S[i]&nbsp;</span><span style="color: #000000">+=</span><span style="color: #000000">&nbsp;S[i&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">];<br />&nbsp;&nbsp;&nbsp;&nbsp;rre(i,&nbsp;n)&nbsp;sa[</span><span style="color: #000000">--</span><span style="color: #000000">S[rank[tmp[i]]]]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;tmp[i];<br /></span></div>注意这个基数排序的过程是很特别的。首先，它并不是对A在进行排序，而是对上一阶段求出的rank在进行排序。因为前面已经说过，在求sa的过程中，rank就是用来代替A的对应长度的子串的，由于不能直接对子串进行排序（那样的话时间开销很恐怖的），所以只能对rank进行排序。另外，这里在对二元组&lt;x, y&gt;的第二关键字（y）进行排序的过程中加了优化：这些y其实就是把上一阶段的sa整体左移了j，右边空出的部分全部用@（空串）填充得到的，由于空串的字典序肯定最小，因此将右边的空串按照下标顺序先写入临时sa（代码中用tmp表示的就是临时sa，也就是对第二关键字y排序后的ord结果），然后，上一阶段的sa如果左移后还木有消失的（也就是sa值大于等于j的），再按顺序写入临时sa，就得到了排序结果。剩下的对x的排序结果就是上一阶段的sa，唯一不同的是对于x相同的，按照临时名次递增的顺序。<br /><br />&lt;4&gt;求出新阶段的rank值：
<div style="border-bottom: #cccccc 1px solid; border-left: #cccccc 1px solid; padding-bottom: 4px; background-color: #eeeeee; padding-left: 4px; width: 98%; padding-right: 5px; font-size: 13px; word-break: break-all; border-top: #cccccc 1px solid; border-right: #cccccc 1px solid; padding-top: 4px"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000">tmp[sa[</span><span style="color: #000000">0</span><span style="color: #000000">]]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;p&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />re2(i,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;n)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;v0&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;sa[i&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">];&nbsp;v1&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;sa[i];<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(v0&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;j&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;n)&nbsp;v00&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;rank[v0&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;j];&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;v00&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(v1&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;j&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;n)&nbsp;v01&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;rank[v1&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;j];&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;v01&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(rank[v0]&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;rank[v1]&nbsp;</span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000">&nbsp;v00&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;v01)&nbsp;tmp[sa[i]]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;p;&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;tmp[sa[i]]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">++</span><span style="color: #000000">p;<br />}<br />re(i,&nbsp;n)&nbsp;rank[i]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;tmp[i];<br />SZ&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">++</span><span style="color: #000000">p;<br /></span></div>由于下一阶段需要使用本阶段的rank值，因此在求出了本阶段的sa值以后，需要求rank值。（代码中的tmp起了临时rank的作用，目的是节省空间）<br />因为sa值已经求出，因此只要依次扫描sa就可以得到rank值，唯一要做的工作就是找到哪些子串是相等的，它们的rank值应该相等，除此之外，rank值只要依次加1即可。判定相等的方法：只需判定rank[i]和rank[i+j]是否都对应相等即可。若rank[i+j]越界，用-&#8734;（当然任何一个负数都行，代码中用了-1）来表示。<br />最后还有一个优化：由于本阶段的名次的范围只有[0..p]这么多，下一阶段的&#8220;字符集&#8221;（其实就是rank集）的大小SZ可以设为p+1，这样可以省一些时间。<br /><br />这样后缀数组sa和名次数组rank就全部求完了。<br /><br />以后还有一些更重要的东东就是AC自动机、后缀数组等的应用问题，算了，以后再搞吧囧。<br /><img src ="http://www.cppblog.com/MatoNo1/aggbug/158926.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MatoNo1/" target="_blank">Mato_No1</a> 2011-10-23 16:51 <a href="http://www.cppblog.com/MatoNo1/archive/2011/10/23/158926.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AC自动机模板题——HDU2222</title><link>http://www.cppblog.com/MatoNo1/archive/2011/10/19/158635.html</link><dc:creator>Mato_No1</dc:creator><author>Mato_No1</author><pubDate>Wed, 19 Oct 2011 11:47:00 GMT</pubDate><guid>http://www.cppblog.com/MatoNo1/archive/2011/10/19/158635.html</guid><wfw:comment>http://www.cppblog.com/MatoNo1/comments/158635.html</wfw:comment><comments>http://www.cppblog.com/MatoNo1/archive/2011/10/19/158635.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/MatoNo1/comments/commentRss/158635.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MatoNo1/services/trackbacks/158635.html</trackback:ping><description><![CDATA[具体题目见<a title="HDU2222" href="http://acm.hdu.edu.cn/showproblem.php?pid=2222">HDU2222</a>，其实就是一个裸的多串匹配的问题（给出一个主串和N个子串，求出几个子串在主串中出现过）。<br /><br />我真是太沙茶了&#8230;&#8230;这么水的题目调了N久，找了N位神犇帮我看代码，最终才找出来BUG&#8230;&#8230;<br /><br />易疵点：<br />（1）本题的子串是可以相同的，此时Trie的每个结点要设一个mul值，表示该结点对应的字符串在所有子串中重复的次数，另外，<span style="color: red"><strong>不要为了省空间把mul定义成char型，有可能所有的字符串全相同，因此需要定义成int（事实证明不会爆空间），这是本沙茶被折磨了这么久的主要原因</strong></span>；<br />（2）Trie采用静态存储，0号结点作为空结点（NULL），因此真正的结点编号从1开始，另外root一般都是1号结点；<br />（3）注意在建立自动机以及匹配的时候，所有要沿fail上溯的地方，其边界都是0（NULL，注意不是root）或者找到一个有对应子结点的结点。注意到0还没有找到的处理方法：在建立自动机的时候，将T[j]置为root；在匹配的时候，将x置为root；<br /><br />代码（模板）（那些标了Attention的地方都是易疵的）： 
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000">#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">iostream</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">stdio.h</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />#include&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">string</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br /></span><span style="color: #0000ff">using</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">namespace</span><span style="color: #000000">&nbsp;std;<br /></span><span style="color: #0000ff">using</span><span style="color: #000000">&nbsp;std::</span><span style="color: #0000ff">string</span><span style="color: #000000">;<br /></span><span style="color: #0000ff">#define</span><span style="color: #000000">&nbsp;re(i,&nbsp;n)&nbsp;for&nbsp;(int&nbsp;i=0;&nbsp;i&lt;n;&nbsp;i++)</span><span style="color: #000000"><br /></span><span style="color: #0000ff">#define</span><span style="color: #000000">&nbsp;root&nbsp;1</span><span style="color: #000000"><br /></span><span style="color: #0000ff">const</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;MAXN&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">500001</span><span style="color: #000000">,&nbsp;MAXLEN&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1000001</span><span style="color: #000000">,&nbsp;SZ&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">26</span><span style="color: #000000">,&nbsp;INF&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">~</span><span style="color: #000000">0U</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&gt;&gt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">2</span><span style="color: #000000">;<br /></span><span style="color: #0000ff">struct</span><span style="color: #000000">&nbsp;node&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;mul,&nbsp;ch[SZ],&nbsp;fail;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">Attention</span><span style="color: #008000"><br /></span><span style="color: #000000">}&nbsp;T[MAXN];<br /></span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;N,&nbsp;Q[MAXN],&nbsp;res;<br /></span><span style="color: #0000ff">string</span><span style="color: #000000">&nbsp;s0,&nbsp;A;<br /></span><span style="color: #0000ff">char</span><span style="color: #000000">&nbsp;tmp[MAXLEN],&nbsp;tmp0[</span><span style="color: #000000">51</span><span style="color: #000000">];<br /></span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;ins()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;len&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;s0.length(),&nbsp;x&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;root,&nbsp;c;<br />&nbsp;&nbsp;&nbsp;&nbsp;re(i,&nbsp;len)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;s0[i]&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">97</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(</span><span style="color: #000000">!</span><span style="color: #000000">T[x].ch[c])&nbsp;{T[x].ch[c]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">++</span><span style="color: #000000">N;&nbsp;T[N].mul&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;&nbsp;re(j,&nbsp;SZ)&nbsp;T[N].ch[j]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;T[x].ch[c];<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;T[x].mul</span><span style="color: #000000">++</span><span style="color: #000000">;<br />}<br /></span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;mkf()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;Q[</span><span style="color: #000000">0</span><span style="color: #000000">]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;root;&nbsp;T[root].fail&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;i,&nbsp;j,&nbsp;x;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">for</span><span style="color: #000000">&nbsp;(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;front</span><span style="color: #000000">=</span><span style="color: #000000">0</span><span style="color: #000000">,&nbsp;rear</span><span style="color: #000000">=</span><span style="color: #000000">0</span><span style="color: #000000">;&nbsp;front</span><span style="color: #000000">&lt;=</span><span style="color: #000000">rear;&nbsp;front</span><span style="color: #000000">++</span><span style="color: #000000">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;Q[front];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;re(k,&nbsp;SZ)&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(j&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;T[i].ch[k])&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;T[i].fail;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">while</span><span style="color: #000000">&nbsp;(x&nbsp;</span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">!</span><span style="color: #000000">T[x].ch[k])&nbsp;x&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;T[x].fail;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">Attention</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(x)&nbsp;T[j].fail&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;T[x].ch[k];&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;T[j].fail&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;root;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">Attention</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Q[</span><span style="color: #000000">++</span><span style="color: #000000">rear]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;j;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /></span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;solve()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;len&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;A.length(),&nbsp;x&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;root,&nbsp;y,&nbsp;c;&nbsp;res&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;re(i,&nbsp;len)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;A[i]&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">97</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">while</span><span style="color: #000000">&nbsp;(x&nbsp;</span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">!</span><span style="color: #000000">T[x].ch[c])&nbsp;x&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;T[x].fail;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">Attention</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(</span><span style="color: #000000">!</span><span style="color: #000000">x)&nbsp;x&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;root;&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;x&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;T[x].ch[c];&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">Attention</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;x;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">while</span><span style="color: #000000">&nbsp;(y)&nbsp;{res&nbsp;</span><span style="color: #000000">+=</span><span style="color: #000000">&nbsp;T[y].mul;&nbsp;T[y].mul&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;&nbsp;y&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;T[y].fail;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">Attention</span><span style="color: #008000"><br /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /></span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;main()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;tests,&nbsp;n;<br />&nbsp;&nbsp;&nbsp;&nbsp;scanf(</span><span style="color: #000000">"</span><span style="color: #000000">%d</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">&amp;</span><span style="color: #000000">tests);<br />&nbsp;&nbsp;&nbsp;&nbsp;re(testno,&nbsp;tests)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;N&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">;&nbsp;T[root].mul&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;&nbsp;re(i,&nbsp;SZ)&nbsp;T[root].ch[i]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scanf(</span><span style="color: #000000">"</span><span style="color: #000000">%d</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">&amp;</span><span style="color: #000000">n);&nbsp;getchar();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;re(i,&nbsp;n)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gets(tmp0);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s0&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;tmp0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ins();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;gets(tmp);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;A&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;tmp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mkf();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;solve();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(</span><span style="color: #000000">"</span><span style="color: #000000">%d\n</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;res);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />}<br /></span></div><br />【2011年10月19日】今天发现了匹配过程中的一个可优化的地方：对于一个点x以及它的所有返回结点（这里把所有沿着x的失败指针不断上溯直到root路径上的结点都称为返回结点），由于不可重复计数，可以将它们的mul值置为原来mul值的相反数（-mul），而不是0，表示该结点已经统计过。这样在下一次y的上溯过程中一旦发现一个mul值为负的点就不用继续上溯了，因为上面的点一定也已经统计过了。<br />当然，这仅限于单主串，如果是多主串则需要在每次匹配之前把Trie树中所有结点的mul值（如果是负数的的话）全部重新取反。为了节省时间，可以在匹配过程中把所有统计过的（mul值改为负数的）结点全部放进一个辅助的队列里，然后取反时只要处理队列中的结点就行了。<br /><br />加入该优化后的代码（solve部分）： 
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;solve()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;len&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;A.length(),&nbsp;x&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;root,&nbsp;y,&nbsp;c;&nbsp;res&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;re(i,&nbsp;len)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;A[i]&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">97</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">while</span><span style="color: #000000">&nbsp;(x&nbsp;</span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">!</span><span style="color: #000000">T[x].ch[c])&nbsp;x&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;T[x].fail;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(</span><span style="color: #000000">!</span><span style="color: #000000">x)&nbsp;x&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;root;&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;x&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;T[x].ch[c];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;x;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">while</span><span style="color: #000000">&nbsp;(y&nbsp;</span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000">&nbsp;T[y].mul&nbsp;</span><span style="color: #000000">&gt;=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">)&nbsp;{res&nbsp;</span><span style="color: #000000">+=</span><span style="color: #000000">&nbsp;T[y].mul;&nbsp;T[y].mul&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">T[y].mul;&nbsp;y&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;T[y].fail;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}</span></div><br />下面是优化的实测结果（第一个为优化后的，第二个为优化前的），可以看出，该优化的力度很大。<img height="48" alt="" src="http://www.cppblog.com/images/cppblog_com/matono1/测评结果/ACauto.gif" width="564" border="0" longdesc="" /><br /><img src ="http://www.cppblog.com/MatoNo1/aggbug/158635.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MatoNo1/" target="_blank">Mato_No1</a> 2011-10-19 19:47 <a href="http://www.cppblog.com/MatoNo1/archive/2011/10/19/158635.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>环形串的最优断点问题</title><link>http://www.cppblog.com/MatoNo1/archive/2011/04/23/144852.html</link><dc:creator>Mato_No1</dc:creator><author>Mato_No1</author><pubDate>Sat, 23 Apr 2011 08:09:00 GMT</pubDate><guid>http://www.cppblog.com/MatoNo1/archive/2011/04/23/144852.html</guid><wfw:comment>http://www.cppblog.com/MatoNo1/comments/144852.html</wfw:comment><comments>http://www.cppblog.com/MatoNo1/archive/2011/04/23/144852.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/MatoNo1/comments/commentRss/144852.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MatoNo1/services/trackbacks/144852.html</trackback:ping><description><![CDATA[【问题描述】<br>给出一个环形的字符串S，长度为N，现在要找到一个断开点，使得从这里断开后的字符串字典序最小。或者说，对于长度为N的字符串S[0..N-1]，找到一个位置i，使得字符串S' = S[i..N-1] + S[0..i-1]的字典序最小。若存在多个这样的最优断点，则取最左边(i最小)的那个。<br>【Sample Input】<br>amandamanda<br>【Sample Output】<br>10<br>（从第10位断开后得到的字符串"aamandamand"的字典序是11个断开位置中最小的）<br><br>【分析】<br>首先将这个环形串拆开：只需将S[0..N-1]的后面再接上S[0..N-2]即可（如对于样例，可构造字符串T = "amandamandaamandamand"），则T的任意一个长度为N的子串T[i..i-N+1]就是S从第i位断开得到的字符串。此时问题就变成了：<span style="COLOR: red"><strong>给出一个长度为(2N-1)的字符串，求出其所有长度为N的子串中字典序最小的</strong></span>。<br><br>设F[x]为<span style="COLOR: red"><strong>T中所有起始位小于N的长度为x的子串中字典序最小的子串的起始位（若有多个则取最左边的）</strong></span>，如对于T="abaabaaababaabaaa"，有F[0]=F[1]=0，F[2]=2，F[3]=F[4]=5&#8230;&#8230;本题的目的就是求出F[N]的值。一开始已知的只有F[0]=0（长度为0的字符串都是空串，字典序都是最小的，取最左边的第0位）。<br><br>可以发现，F数组有很多重要的性质：<br><span style="COLOR: #ff0000"><strong>性质1 F[0..N]数组是单调递增的。</strong></span><br>证明：用反证法。设存在一个值x(0&lt;=x&lt;N)使得F[x]&gt;F[x+1]则根据定义，有T[F[x+1]..F[x+1]+x]&lt;=T[F[x]..F[x]+x]（这里一定不会越界，即F[x]+x的值一定不大于(2N-1)，因为x&lt;N，又根据得F[x]&lt;N，故F[x]+x&lt;2N），这样，必有T[F[x+1]..F[x+1]+x-1]&lt;=T[F[x]..F[x]+x-1]。然而根据F[x]的定义又可以得到T[F[x+1]..F[x+1]+x-1]&gt;T[F[x]..F[x]+x-1]（否则F[x]的值就应该等于F[x+1]的值了），矛盾，故在F[0..N]中不可能存在任何F[x]&gt;F[x+1]的情况，也即F[0..N]数组是单调递增的（以下将F[0..N]数组简称为F数组）。<br><span style="COLOR: #ff0000"><strong>性质2 对于任意值x(0&lt;=x&lt;N)，必然满足F[x+1]=F[x]或F[x+1]&gt;F[x]+x。</strong></span><br>证明：因为前面已经证明了F数组是单调递增的，这里只需证明对于任意x(0&lt;=x&lt;N)，不存F[x]&lt;F[x+1]&lt;=F[x]+x的情况即可。<br>这里同样用反证法。设存在一个值x(0&lt;=x&lt;N)使得F[x]&lt;F[x+1]&lt;=F[x]+x。则根据定义有T[F[x+1]..F[x+1]+x]&lt;T[F[x]..F[x]+x]且T[F[x]..F[x]+x-1]&lt;=T[F[x+1]..F[x+1]+x-1]，这样必有T[F[x]..F[x]+x-1]=T[F[x+1]..F[x+1]+x-1]且T[F[x+1]+x]&lt;T[F[x]+x]。设D=F[x+1]-F[x]，则T[F[x]]=T[F[x]+D]，因为D&lt;=x，可得T[F[x]+D]=T[F[x]+2D]，即T[F[x]]=T[F[x]+2D]。这样，T[F[x]..F[x]+x-D-1]=T[F[x]+2D..F[x]+x+D-1]；又因为T[F[x]+x-D]=T[F[x]+x]，而T[F[x+1]+x]（即T[F[x]+x+D]]）&lt;T[F[x]+x]，这样，T[F[x]+x+D]&lt;T[F[x]+x-D]，也就是，T[F[x]+2D..F[x]+x+D]&lt;T[F[x]..F[x]+x-D]！这样可以得出，从(F[x]+2D)位开始的任意长度不小于(x-D)的子串，其字典序都小于从F[x]位开始的同样长度的子串，由于F[x]&lt;F[x+1]&lt;=F[x]+x，D=F[x+1]-F[x]，所以有1&lt;=D&lt;=x，这样，F[x]的值就应该是(F[x]+2D)了，这显然不可能。所以，一开始假设的这种情况是不可能存在的，即对于任意值x（0&lt;=x&lt;N），必然满足F[x+1]=F[x]或F[x+1]&gt;F[x]+x。<br><br>根据F数组的以上两个性质可以设计出本题的算法：<br>设目前已经求出了F[0..x-1]的值，且F[x-1]=i。首先将T[0..i-1]全部删去（因为F数组是单调递增的，F[x]的值一定不小于i），然后对T自身作扩展KMP（就是以T为模板串，T为子串的扩展KMP，相当于其预处理部分），一开始先将F[x]置为i，设第j位的匹配长度为next[j]，若next[j]=x-1且T[j+x-1]&lt;T[i+x-1]，则将F[x]的值改为j，这样扫描一遍，即求出了F[x]的值。若扫描过程中未出现任何next[j]=x-1，则设所有next[j]值不小于x的最小next[j]值为y，则可以直接得到F[x..y-1]的值均等于F[x-1]。就这样直到求出F[N]的值为止。<br><br>时间复杂度：O(N<span style="FONT-FAMILY: symbol">&#214;</span>N)，可以根据性质2得到。
<img src ="http://www.cppblog.com/MatoNo1/aggbug/144852.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MatoNo1/" target="_blank">Mato_No1</a> 2011-04-23 16:09 <a href="http://www.cppblog.com/MatoNo1/archive/2011/04/23/144852.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>KMP和扩展KMP</title><link>http://www.cppblog.com/MatoNo1/archive/2011/04/17/144390.html</link><dc:creator>Mato_No1</dc:creator><author>Mato_No1</author><pubDate>Sun, 17 Apr 2011 11:11:00 GMT</pubDate><guid>http://www.cppblog.com/MatoNo1/archive/2011/04/17/144390.html</guid><wfw:comment>http://www.cppblog.com/MatoNo1/comments/144390.html</wfw:comment><comments>http://www.cppblog.com/MatoNo1/archive/2011/04/17/144390.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/MatoNo1/comments/commentRss/144390.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/MatoNo1/services/trackbacks/144390.html</trackback:ping><description><![CDATA[KMP：给出两个字符串A（称为模板串）和B（称为子串），长度分别为lenA和lenB，要求在线性时间内，对于每个A[i]（0&lt;=i&lt;lenA)，求出A[i]往前和B的前缀匹配的最大匹配长度，记为ex[i]（或者说，ex[i]为满足A[i-z+1..i]==B[0..z-1]的最大的z值）。KMP的主要目的是求B是不是A的子串，以及若是，B在A中所有出现的位置（当ex[i]=lenB时）。<br />【算法】<br />设next[i]为满足B[i-z+1..i]==B[0..z-1]的最大的z值（也就是B的自身匹配）。设目前next[0..lenB-1]与ex[0..i-1]均已求出，要用它们来求ex[i]的值。<br />根据ex的定义，有A[i-1-ex[i-1]+1..i-1]==B[0..ex[i-1]-1]，这时，若有A[i]==B[ex[i-1]]，则可以直接得到ex[i]=ex[i-1]+1（因为i-1-ex[i-1]+1即i-ex[i-1]，现在由于A[i]==B[ex[i-1]]，可得A[i-ex[i-1]..i]==B[0..ex[i-1]]，即A[i-ex[i-1]+1-1..i]==B[0..ex[i-1]+1-1]，所以ex[i]=ex[i-1]+1）。若A[i]!=B[ex[i-1]]？<br />设j=next[ex[i-1]-1]，则根据next定义得B[ex[i-1]-j..ex[i-1]-1]==B[0..j-1]，又因为A[i-ex[i-1]..i-1]==B[0..ex[i-1]-1]得A[i-j..i-1]==B[ex[i-1]-j..ex[i-1]-1]，这样有<span style="color: red"><strong>A[i-j..i-1]==B[0..j-1]</strong></span>！也就是此时只需再比较A[i]与B[j]的值是否相等即可，若相等，可得ex[i]=j+1，若仍不相等，则更新j为next[j-1]，继续比较A[i]与B[j]是否相等&#8230;&#8230;直到A[i]与B[j]相等或直到j==0时，A[i]仍不等于B[j]，此时ex[i]=0。边界：求ex[0]时，初始j（用来代替ex[i-1]）为0。<br />现在还有一个问题，如何求next？显然next就是以B自身为模板串，B为子串的&#8220;自身匹配&#8221;，用类似的办法即可，唯一不同的是next[0]=lenB可以直接得到，求next[1]时，初始j（代替next[i-1]）为0。<br />【核心代码】<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;lenA&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;strlen(A);&nbsp;lenB&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;strlen(B);<br />&nbsp;&nbsp;&nbsp;&nbsp;next[</span><span style="color: #000000">0</span><span style="color: #000000">]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;lenB;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;j&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;re2(i,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;lenB)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">while</span><span style="color: #000000">&nbsp;(j&nbsp;</span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000">&nbsp;B[i]&nbsp;</span><span style="color: #000000">!=</span><span style="color: #000000">&nbsp;B[j])&nbsp;j&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;next[j&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(B[i]&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;B[j])&nbsp;j</span><span style="color: #000000">++</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;next[i]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;j;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;j&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;re(i,&nbsp;lenA)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">while</span><span style="color: #000000">&nbsp;(j&nbsp;</span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000">&nbsp;A[i]&nbsp;</span><span style="color: #000000">!=</span><span style="color: #000000">&nbsp;B[j])&nbsp;j&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;next[j&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(A[i]&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;B[j])&nbsp;j</span><span style="color: #000000">++</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ex[i]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;j;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span></div>
扩展KMP：给出模板串A和子串B，长度分别为lenA和lenB，要求在线性时间内，对于每个A[i]（0&lt;=i&lt;lenA)，求出A[i..lenA-1]与B的最长公共前缀长度，记为ex[i]（或者说，ex[i]为满足A[i..i+z-1]==B[0..z-1]的最大的z值）。扩展KMP可以用来解决很多字符串问题，如求一个字符串的最长回文子串和最长重复子串。<br />【算法】<br />设next[i]为满足B[i..i+z-1]==B[0..z-1]的最大的z值（也就是B的自身匹配）。设目前next[0..lenB-1]与ex[0..i-1]均已求出，要用它们来求ex[i]的值。<br />设p为目前A串中匹配到的最远位置，k为让其匹配到最远位置的值（或者说，k是在0&lt;=i0&lt;i的所有i0值中，使i0+ex[i0]-1的值最大的一个，p为这个最大值，即k+ex[k]-1），显然，p之后的所有位都是未知的，也就是目前还无法知道A[p+1..lenA-1]中的任何一位和B的任何一位是否相等。<br />根据ex的定义可得，A[k..p]==B[0..p-k]，因为i&gt;k，所以又有A[i..p]==B[i-k..p-k]，设L=next[i-k]，则根据next的定义有B[0..L-1]==B[i-k..i-k+L-1]。考虑i-k+L-1与p-k的关系：<br />（1）i-k+L-1&lt;p-k，即i+L&lt;=p。这时，由A[i..p]==B[i-k..p-k]可以得到A[i..i+L-1]==B[i-k..i-k+L-1]，又因为B[0..L-1]==B[i-k..i-k+L-1]所以A[i..i+L-1]==B[0..L-1]，这就说明ex[i]&gt;=L。又由于next的定义可得，A[i+L]必然不等于B[L]（否则A[i..i+L]==B[0..L]，因为i+L&lt;=p，所以A[i..i+L]==B[i-k..i-k+L]，这样B[0..L]==B[i-k..i-k+L]，故next[i-k]的值应为L+1或更大），这样，<span style="color: red"><strong>可以直接得到ex[i]=L！</strong></span><br />（2）i+k-L+1&gt;=p-k，即i+L&gt;p。这时，首先可以知道A[i..p]和B[0..p-i]是相等的（因为A[i..p]==B[i-k..p-k]，而i+k-L+1&gt;=p-k，由B[0..L-1]==B[i-k..i-k+L-1]可得B[0..p-i]==B[i-k..p-k]，即A[i..p]==B[0..p-i]），然后，对于A[p+1]和B[p-i+1]是否相等，目前是不知道的（因为前面已经说过，p是目前A串中匹配到的最远位置，在p之后无法知道任何一位的匹配信息），因此，要从A[p+1]与B[p-i+1]开始往后继续匹配（设j为目前B的匹配位置的下标，一开始j=p-i+1，每次比较A[i+j]与B[j]是否相等，直到不相等或者越界为止，此时的j值就是ex[i]的值）。在这种情况下，p的值必然会得到延伸，因此更新k和p的值。<br />边界：ex[0]的值需要预先求出，然后将初始的k设为0，p设为ex[0]-1。<br />对于求next数组，也是&#8220;自身匹配&#8221;，类似KMP的方法处理即可。唯一的不同点也在边界上：可以直接知道next[0]=lenB，next[1]的值预先求出，然后初始k=1，p=ex[1]。<br /><br /><strong><span style="color: red;">需要严重注意的是，在上述的情况（2）中，本该从A[p+1]与B[p-i+1]开始匹配，但是，若p+1&lt;i，也就是p-i+1&lt;0（这种情况是有可能发生的，当ex[i-1]=0，且前面的ex值都没有延伸到i及以后的时候）的话，需要将A、B的下标都加1（因为此时p必然等于i-2，如果A、B的下标用两个变量x、y控制的话，x和y都要加1）！！</span></strong><br /><br />【核心代码】<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #000000">lenA&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;strlen(A);&nbsp;lenB&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;strlen(B);<br />&nbsp;&nbsp;&nbsp;&nbsp;next[</span><span style="color: #000000">0</span><span style="color: #000000">]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;lenB;&nbsp;next[</span><span style="color: #000000">1</span><span style="color: #000000">]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;lenB&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;re(i,&nbsp;lenB</span><span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">)&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(B[i]&nbsp;</span><span style="color: #000000">!=</span><span style="color: #000000">&nbsp;B[i&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">])&nbsp;{next[</span><span style="color: #000000">1</span><span style="color: #000000">]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;i;&nbsp;</span><span style="color: #0000ff">break</span><span style="color: #000000">;}<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;j,&nbsp;k&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;p,&nbsp;L;<br />&nbsp;&nbsp;&nbsp;&nbsp;re2(i,&nbsp;</span><span style="color: #000000">2</span><span style="color: #000000">,&nbsp;lenB)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;k&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;next[k]&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">;&nbsp;L&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;next[i&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;k];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(i&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;L&nbsp;</span><span style="color: #000000">&lt;=</span><span style="color: #000000">&nbsp;p)&nbsp;next[i]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;L;&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;j&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;p&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;i&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(j&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">)&nbsp;j&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">while</span><span style="color: #000000">&nbsp;(i&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;j&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;lenB&nbsp;</span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000">&nbsp;B[i&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;j]&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;B[j])&nbsp;j</span><span style="color: #000000">++</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;next[i]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;j;&nbsp;k&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;i;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;minlen&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;lenA&nbsp;</span><span style="color: #000000">&lt;=</span><span style="color: #000000">&nbsp;lenB&nbsp;</span><span style="color: #000000">?</span><span style="color: #000000">&nbsp;lenA&nbsp;:&nbsp;lenB;&nbsp;ex[</span><span style="color: #000000">0</span><span style="color: #000000">]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;minlen;<br />&nbsp;&nbsp;&nbsp;&nbsp;re(i,&nbsp;minlen)&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(A[i]&nbsp;</span><span style="color: #000000">!=</span><span style="color: #000000">&nbsp;B[i])&nbsp;{ex[</span><span style="color: #000000">0</span><span style="color: #000000">]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;i;&nbsp;</span><span style="color: #0000ff">break</span><span style="color: #000000">;}<br />&nbsp;&nbsp;&nbsp;&nbsp;k&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;re2(i,&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">,&nbsp;lenA)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;p&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;k&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;ex[k]&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">;&nbsp;L&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;next[i&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;k];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(i&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;L&nbsp;</span><span style="color: #000000">&lt;=</span><span style="color: #000000">&nbsp;p)&nbsp;ex[i]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;L;&nbsp;</span><span style="color: #0000ff">else</span><span style="color: #000000">&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;j&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;p&nbsp;</span><span style="color: #000000">-</span><span style="color: #000000">&nbsp;i&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(j&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">)&nbsp;j&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">0</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">while</span><span style="color: #000000">&nbsp;(i&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;j&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;lenA&nbsp;</span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000">&nbsp;j&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;lenB&nbsp;</span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000">&nbsp;A[i&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;j]&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;B[j])&nbsp;j</span><span style="color: #000000">++</span><span style="color: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ex[i]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;j;&nbsp;k&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;i;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span></div>
【时间复杂度分析】<br />在KMP和扩展KMP中，不管是A串还是B串，其匹配位置都是单调递增的，故总时间复杂度是线性的，都为O(lenA + lenB)（只是扩展KMP比KMP的常数更大一些）。<br />【应用】<br />KMP和扩展KMP在解决字符串问题中有大用。很多看上去很猥琐的字符串问题，都可以归结到这两种算法之中。另外，这里的&#8220;字符串&#8221;可以延伸为一切类型的数组，而不仅仅是字符数组。<img src ="http://www.cppblog.com/MatoNo1/aggbug/144390.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/MatoNo1/" target="_blank">Mato_No1</a> 2011-04-17 19:11 <a href="http://www.cppblog.com/MatoNo1/archive/2011/04/17/144390.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>