Manacher算法总结

来源:互联网 发布:ui设计网站知乎 编辑:程序博客网 时间:2024/05/30 22:42

Manacher算法总结

算法功能:

Manacher最主要的功能就是求一串字符中的最长回文子串的长度。

算法核心代码:

第一种:

int nextstr()      //对输入的字符串进行预处理,将字符中间插入一个不可能出现的字符。

{

   s[0]='&';            //为了防止字符串越界,所以将储存字符的字符串开头的赋值为另一个不同的字符。

   int n=strlen(str);

   for(int i=1;i<=n*2;i+=2){

       s[i]='#';

       s[i+1]=str[i/2];

    }

   s[n*2+1]='#';    //最字符串最后的进行处理。

   s[n*2+2]='\0'; 

   return n*2+1;

}

int manacher ()         // manacher这是算法的主体部分;

{

   int i,j,maxx=0,id=0;

   int len=nextstr();               //len记录的是处理之后字符串的长度;

   for(i=1;i<=len;i++){

       if(id+q[id]>i)

           q[i]=min(q[id]+id-i,q[2*id-i]);             //如果i点在以id为中心的回文字符串的长度范围之内,则去i点到边界的值和i点关于id点对称的点的回文串的长度;

       else q[i]=1;

       while(s[i+q[i]]==s[i-q[i]])            //找出以i点中心的字符子串的长度;

           q[i]++;

       maxx=max(maxx,q[i]);              //记录最长的回文串的长度;

       if(q[i]+i>id+q[id])

           id=i;

    }

   return maxx-1;

}

第二种:                   //这种方法和第一中的差别不打,最主要的差别是对字符串处理的函数上,第一中方法处理后需要用一个新的字符串来储存,而第二种方法则直接在原来字符串中修改;

void change ()

{

   for(int i=len;i>=0;i--){

       str[i*2+1]='#';

       str[i*2+2]=str[i];

    }

}

void manacher ()

{

   int i,j,id=0;

   for(i=2;i<=len*2+1;i++){

       if(p[id]+id>i)

           p[i]=min(p[2*id-i],p[id]+id-i);

       else p[i]=0;

       while(str[i-p[i]]==str[i+p[i]])

           ++p[i];

       if(id+p[id]<i+p[i])

           id=i;

    }

}

原创粉丝点击