O(n)回文子串(Manacher)算法
最近由于某些需要,想重新找了一些这个算法的相关资料,发现部分ACMer转载了成电OJ的BBS上这篇文章,我想了一发,与其让别人来转载,还不如让我自己把它发出来。
原地址:http://acm.uestc.edu.cn/bbs/read.php?tid=3258
这里,我介绍一下O(n)回文串处理的一种方法。Manacher算法.
原文地址:
好,到这里,我们可以先贴一份代码了。
1 void pk()
2 {
3 int i;
4 int mx = 0;
5 int id;
6 for(i=1; i<n; i++)
7 {
8 if( mx > i )
9 p[i] = MIN( p[2*id-i], mx-i );
10 else
11 p[i] = 1;
12 for(; str[i+p[i]] == str[i-p[i]]; p[i]++)
13 ;
14 if( p[i] + i > mx )
15 {
16 mx = p[i] + i;
17 id = i;
18 }
19 }
20 }
代码是不是很短啊,而且相当好写。很方便吧,还记得我上面说的这个算法避免了很多不必要的重复匹配吧。这是什么意思呢,其实这就是一句代码。
if( mx > i )
p[i] = MIN( p[2*id-i], mx-i );
就是当前面比较的最远长度mx>i的时候,P[i]有一个最小值。这个算法的核心思想就在这里,为什么P数组满足这样一个性质呢?
(下面的部分为图片形式)
看完这个算法,你有可能会觉得这种算法在哪会用到呢?其实回文串后缀数组也可以做。只是复杂度是O(n log n)的,而且一般情况下也不会刻意去卡一个log n的算法。可正好hdu就有这么一题,你用后缀数组写怎么都得T(当然应该是我写得太烂了)。不信的话大家也可以去试试这题。
http://acm.hust.edu.cn:8080/judge/problem/viewSource.action?id=140283