Manacher算法

来源:互联网 发布:零基础学编程 编辑:程序博客网 时间:2024/05/24 07:31

Manacher算法,一个神奇的求字符串中 以所有可能位置为中心的最长回文子串长度。复杂度只有O(n),n为字符串长度,却能求出所有位置的最长回文子串长度,子串限定条件是连续的子串。 

算法中需要插入特殊字符,该字符需满足不存在于原字符串中。


详细原理可查询网上相关资料  点击打开链接


以下为51nod 1089 题的提交AC代码。


仔细思考后,发现网上的代码中应该都有冗余项,以下代码中GetPalindromLength()函数中的开始的if语句其实并不需要,开始部分可以直接改成

 int mid_id = 1, right_id = 2;
 for (int i = 1; i < mylen; ++i)
 {
  p[i] = min(p[2 * mid_id - i], right_id - i);

程序仍然AC。


#include <cstdio>#include <algorithm>#include <iostream>#define  maxlen  200010#define insert_ch  '#'#define start_ch  '*'char my_ch[maxlen];int p[maxlen];int mylen;using namespace std;void PrePrecess(char *tmp_str)//功能为求得每个字符为中心的最长回文字符串,所以需要预处理,必须保证存在一个可插入的不存在字符{char *my_ptr = my_ch, *tmp_ptr1 = tmp_str;if (*tmp_ptr1){*my_ptr++ = start_ch;*my_ptr++ = insert_ch;while (*tmp_ptr1){*my_ptr++ = *tmp_ptr1++;*my_ptr++ = insert_ch;}}}void GetPalindromLength(char *my_ch)//得到p数组,存储以每个字符为中心的最长回文字符串,必须保证存在一个可插入的不存在字符{memset(p, 0, sizeof(p));mylen = strlen(my_ch);int mid_id = 0, right_id = 0;for (int i = 1; i < mylen; ++i){if (right_id>i){p[i] = min(p[2 * mid_id - i], right_id - i);}else{p[i] = 1;}for (; my_ch[i + p[i]] == my_ch[i - p[i]]; ++p[i]);if (p[i] + i > right_id){mid_id = i;right_id = p[i] + i;}}}void Myprint(){//printf("\n");int result = 0;for (int i = 0; i < mylen; ++i){if (result < p[i]){result = p[i];}//printf("%d\t%d\n", i, p[i]);}printf("%d", result-1);}int main(){char tmp_ch[maxlen];scanf("%s", &tmp_ch);//cout << strlen(tmp_ch) << endl;PrePrecess(tmp_ch);//printf("%s\s", my_ch);GetPalindromLength(my_ch);Myprint();return 0;}


0 0
原创粉丝点击