马拉车算法

思路笔记: 

 马拉车算法_第1张图片

马拉车算法_第2张图片

上述情况1和情况2又可以归结为:【i’的回文半径】和【R-i的距离】中小的那个就是i的回文半径。 

#include
#include
#include
using namespace std;


string manacherString(string str) {
	string res = "";
	int index = 0;
	for (int i = 0; i != 2*str.length()+1; ++i) {//偶数位置就是以0结尾的i&1就是偶数部分,i递增,i&1就是求0,2,4,6,8...
		(i & 1) == 0 ? res+="#" : res+=str[index++];
	}
	return res;
}
int min(int a, int b) {
	return a < b ? a : b;
}
int max(int a, int b) {
	return a > b ? a : b;
}
int manacher(string str) {
	if (str.length() == 0)
		return 0;
	string newStr = manacherString(str);
	int pArr_len = newStr.length();
	int *pArr = new int[pArr_len];//pArr会问半径数组
	int C = -1;//中心点从-1开始
	int R = -1;
	int MAX = INT_MIN;
	for (int i = 0; i != newStr.length(); ++i) {
		if (R > i)//i在R边界内
			pArr[i] = min(pArr[2 * C - i], R - i);
		else
			pArr[i] = 1;//i在R边界外
		while (i + pArr[i]-1) {//继续往下扩,保证扩出来不越界就可以了
			if (newStr[i + pArr[i]] == newStr[i - pArr[i]])
				pArr[i]++;
			else
				break;
		}
		if (i + pArr[i] > R) {
			R = i + pArr[i];//最右回文右边界更新为i+pArr[i]
			C = i;
		}
		MAX = max(MAX, pArr[i]);
	}
	return MAX-1;
}
int main() {
	string str;
	while (cin >> str) {
		cout << manacherString(str) << endl;
		cout << manacher(str) << endl;
	}
	return 0;
}

  应用:如果向字符串后面追加字符串成为回文串,怎么添加的字符最少。

例子:abc12321,则添加后abc12321cba

思路:它就是在求包含最后一个字符情况下最长回文串是多少,再将前面不是的部分逆序过来就是答案。其实就是在找回文右边界(R),直到回文右边界到最后一个字符确定当前的C,利用R将L求出来,然后原字符串0~L位置的逆序追加上去即可。

 

你可能感兴趣的:(牛客算法)