马拉车算法
马拉车算法查找 字符串的最大回文子串。
其算法本质上是中心扩展法。
中心扩展法
vector<int> v(strLen,0); //v[i] 是指以i为中心的回文字符串长度的半径
for (int i = 1; i < strLen - 1; i++)
while (str[i + 1 + v[i]] == str[i - 1 - v[i]]) ++v[i];//不考虑越界
而马拉车利用回文的对称性避免多余的计算
核心算法如图所示
是的,最核心的就这个了。
剩下的是解决回文字符串长度是奇数还是偶数(利用插入其它字符)
以及如何更新可利用的A点(当可利用的A点范围比最新的 “A"点 要小时,就更新A点)
附poj 3974 AC代码
int mlc(string &str) {
if (str.size() == 0) return 0;
string newStr;
newStr.push_back('^');
newStr.push_back('#');
int len = str.size();
for (int i = 0; i < len; i++) {
newStr.push_back(str[i]);
newStr.push_back('#');
}
newStr.push_back('$');
int newLen = newStr.size();
vector<int> v(newLen,0);
int C = 0, R = 0;
for (int i = 1; i < newLen - 1; i++) {
int i_mirror = 2 * C - i;
if (R > i)
v[i] = min(R - i, v[i_mirror]);
while (newStr[i + 1 + v[i]] == newStr[i - 1 - v[i]]) {
++v[i];
}
if (i + v[i] > R) {
C = i;
R = i + v[i];
}
}
int ret = 1;
for (int i = 1; i < newLen - 1; i++) {
ret = max(ret, v[i]);
}
return ret;
}
int main() {
string str;
int idx = 0;
for (; ; ) {
cin >> str;
if (str == "END") {
break;
}
int len = mlc(str);
cout << "Case " << ++idx << ": " << len << endl;
}
return 0;
}