在字符串处理中,最长回文子串是一个经典问题。暴力方法时间复杂度高(O(n³)),而Manacher算法可以在线性时间 O(n) 内解决该问题。本教程将用通俗易懂的方式,带你从零掌握 C语言实现Manacher算法 的全过程,即使你是编程小白也能轻松理解!
回文字符串是指正着读和反着读都一样的字符串,例如:"aba"、"abba"、"racecar" 等。
传统方法如中心扩展法虽然直观,但最坏情况下时间复杂度为 O(n²),对于长字符串效率较低。Manacher算法通过巧妙利用回文的对称性,将时间复杂度优化到 O(n),是解决最长回文子串问题的最优解之一。

Manacher算法的关键在于以下两点:
#),将奇偶长度回文统一处理。R 和其对应的中心 C,利用已计算的信息避免重复比较。例如原字符串 s = "abba",预处理后变为 t = "#a#b#b#a#"。这样所有回文都变成奇数长度,便于统一处理。
P[i] 表示以位置 i 为中心的回文半径(包含中心)。例如在 t = "#a#b#b#a#" 中,若 P[4] = 4,说明以索引4为中心的回文长度为4,对应原字符串中的 "bb"。
设当前遍历到位置 i,已知最右边界 R 和中心 C:
i < R,则可利用对称点 j = 2*C - i 的信息,令 P[i] = min(P[j], R - i)。P[i]。R,则更新 C = i,R = i + P[i]。#include <stdio.h>#include <stdlib.h>#include <string.h>// 预处理字符串:在字符间插入 '#'char* preprocess(const char* s) { int len = strlen(s); char* t = (char*)malloc(sizeof(char) * (2 * len + 3)); t[0] = '^'; // 起始哨兵 t[1] = '#'; for (int i = 0; i < len; i++) { t[2 * i + 2] = s[i]; t[2 * i + 3] = '#'; } t[2 * len + 2] = '$'; // 结束哨兵 t[2 * len + 3] = '\0'; return t;}int manacher(const char* s) { char* t = preprocess(s); int n = strlen(t); int* P = (int*)calloc(n, sizeof(int)); int C = 0, R = 0; // 中心和最右边界 int maxLen = 0; for (int i = 1; i < n - 1; i++) { int mirror = 2 * C - i; // i 关于 C 的对称点 // 如果 i 在 R 内部,利用对称性 if (i < R) { P[i] = (R - i) < P[mirror] ? (R - i) : P[mirror]; } // 尝试扩展回文 while (t[i + (1 + P[i])] == t[i - (1 + P[i])]) { P[i]++; } // 如果扩展超过了 R,更新中心和边界 if (i + P[i] > R) { C = i; R = i + P[i]; } // 更新最大回文长度 if (P[i] > maxLen) { maxLen = P[i]; } } free(t); free(P); return maxLen;}int main() { char s[] = "abcbabba"; int len = manacher(s); printf("最长回文子串长度: %d\n", len); return 0;}
^ 和 $ 作为哨兵,防止越界。P[i] 存储的是预处理后字符串中以 i 为中心的回文半径。maxLen 即为原字符串中最长回文子串的长度。通过本教程,你已经掌握了 Manacher算法 的核心思想与 C语言实现。该算法是解决最长回文子串问题的高效方案,也是面试和竞赛中的高频考点。建议动手敲一遍代码,加深理解!
记住这四个关键词:Manacher算法、C语言回文字符串、最长回文子串、字符串算法教程,它们将帮助你在搜索引擎中快速找到相关资源。
本文由主机测评网于2025-12-19发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://www.vpshk.cn/20251210217.html