ACM随笔 17.8.31

来源:互联网 发布:正规淘宝刷客平台 编辑:程序博客网 时间:2024/05/17 02:11

开学四天了,基本天天满课,感觉做ACM的时间明显减少了,这两天晚上也看了一些算法,但是还没有来得及写博客。今天有一场网络赛,不过只A了个签到题,打了个表过了.,刚开始WA了两次,主要原因是HDU上不能用pow,改了一下用自定义就过了。

顺便写一下晚上看的Manacher算法。

这个算法所求的是一个字符串的最长回文串的长度。

在字符串的每一个字符的两边都加上一个该字符串中未出现的字符

比如abba变为#a#b#b#a#

使得所有的字符串都变为奇数。

为了进一步减少程序复杂度,可以在程序的边上加上一个特殊字符免去处理越界的情况。

用p[i]来记录以字符S[i]为中心的最长回文子串向两侧的长度。

 下面计算P[i],该算法增加两个辅助变量id和mx,其中id表示最大回文子串中心的位置,mx则为id+P[id],也就是最大回文子串的边界。
如果mx > i,那么P[i] >= MIN(P[2 * id - i], mx - i)。

当 mx - i > P[j] 的时候,以S[j]为中心的回文子串包含在以S[id]为中心的回文子串中,由于 i 和 j 对称,以S[i]为中心的回文子串必然包含在以S[id]为中心的回文子串中,所以必有 P[i] = P[j]。

 当 P[j] > mx - i 的时候,以S[j]为中心的回文子串不完全包含于以S[id]为中心的回文子串中,也就是说以S[i]为中心的回文子串,其向右至少会扩张到mx的位置,也就是说 P[i] >= mx - i。至于mx之后的部分是否对称,就只能一个一个匹配了。

 对于 mx <= i 的情况,无法对 P[i]做更多的假设,只能P[i] = 1,然后再去匹配了
给出一个样例函数:

 #include <iostream>
#include <string>
#include <cstring>
using namespace std;
void findBMstr(string& str)
{    
int *p = new int[str.size() + 1];
    memset(p, 0, sizeof(p));    
int mx = 0, id = 0;    
for(int i = 1; i <=  str.size(); i++)
    {       
        if(mx > i)
        {
            p[i] = (p[2*id - i] < (mx - i) ? p[2*id - i] : (mx - i));
        }        
else
        {
            p[i] = 1;
        }        
while(str[i - p[i]] == str[i + p[i]])
            p[i]++;       
if(i + p[i] > mx)
        {
            mx = i + p[i];
            id = i;
        }
    }    
int max = 0, ii;    
for(int i = 1; i < str.size(); i++)
    {        
if(p[i] > max)
        {
            ii = i;
            max = p[i];
        }
    }
    max--;    
int start = ii - max ;    
int end = ii + max;    
for(int i = start; i <= end; i++)
    {
        if(str[i] != '#')
        {
            cout << str[i];
        }
    }
    cout << endl;
    delete  p;
}
int main()
{   
string str = "12212321";   
string str0;
    str0 += "$#";   
for(int i = 0; i < str.size(); i++)
    {
        str0 += str[i];
        str0 += "#";
    }
    cout << str0 << endl;
    findBMstr(str0);    
return 0;
}