E-Dreamer

脚踏实地,仰望星空

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

马拉车(Manacher)算法(具体算法流程看这个哥们的:https://blog.csdn.net/qq_35065720/article/details/104205920):

算法解决:在一个字符串中找到最长的回文字符串。
实现策略: 
以每个位置作为中心,向两边扩展,可以确定奇回文,但是偶回文无法这样做。
解决方法:在字符串中间及两边插入某种字符,此时可以按照这种方法进行扩展。此时无论奇回文还是偶回文都可以找到。
例如11211,此时添加任意字符在两边#1#1#2#1#1#此时均可以进行回文判断。
 
C++代码实现:
class Solution1 {
public: 
	char* manacherString(string str) {
		char* charArr = new char[str.size() * 2 + 1];
		int str_len = str.size();
		for (int i = 1; i <= str_len; i++) {
			charArr[2 * i] = str[i - 1];
			charArr[2 * i + 1] = '#';
		}
		return charArr;
	}

	int maxLcpsLength(string str) {
		if (str.size() == 0) {
			return 0;
		}
		char* charArr = manacherString(str);
		vector<int> pArr(strlen(charArr)); // 回文半径数组
		int C = -1;
		int R = -1;
		int max_val = INT_MIN;
		for (int i = 0; i != strlen(charArr); i++) {
			pArr[i] = R > i ? min(pArr[2 * C - i], R - i) : 1;
			// R > i 表示 i在回文右边界里面,有一个不用验的区域
			//  2*C-i 为 i关于C的对称点i',两个瓶颈:1.i'的回文半径 2. R到我(i)的距离
			while (i + pArr[i] < strlen(charArr) && i - pArr[i] > -1) { // 左右两边都不越界
				if (charArr[i + pArr[i]] == charArr[i - pArr[i]]) { // 在不用验的区域下再扩一下
					pArr[i]++;
				}
				else {
					break;
				}
			}
			if (i + pArr[i] > R) {
				R = i + pArr[i]; // 更新右边界
				C = i;           // 更新中心位置
			}
			max_val = max(max_val, pArr[i]); // 全局最大值
		}
		return max_val - 1;
	}
};

  

 
 
posted on 2020-04-06 16:45  E-Dreamer  阅读(239)  评论(0编辑  收藏  举报