馬拉車算法

思路筆記: 

 

上述情況1和情況2又可以歸結爲:【i’的迴文半徑】和【R-i的距離】中小的那個就是i的迴文半徑。 

#include<iostream>
#include<stack>
#include<string>
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]<pArr_len && 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位置的逆序追加上去即可。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章