1. 程式人生 > 其它 >[學習筆記]迴文演算法

[學習筆記]迴文演算法

生命是終將荒蕪的渡口,連我們自己都是過客。

Manacher

Manacher用以解決一類對每個中心求解其左右兩端最長的迴文串。

考慮我們先把所有兩個字元之間都插入一個不在字符集裡的字元,這樣就可以不用考慮中心在字元中間的情況,即可以直接列舉中心。

考慮如何使用已知的資訊操作。

若我們求\(i\)位置的最長迴文半徑,設前面極長迴文串的最右端為中心為第\(j\)個位置,考慮對稱過去為\(p\),則不難發現\(\min(f_p,j + f_j - i)\)一定不大於\(f_i\),我們就可以知道在我們已經掃過的範圍內,以\(i\)位置為迴文中心的迴文串的最長迴文半徑,接著可以之間暴力列舉。

其複雜度為\(O(n)\)

點選檢視程式碼
	s[0] = '~';
	a = getchar();
	while(a <= 'z' && a >= 'a'){
		s[++len] = '|';
		s[++len] = a;
		a = getchar();
	}
	s[++len] = '|';
	for(int i = 1;i <= len;++i){
		if(m + ans[m] >= i)
		ans[i] = std::min(m + ans[m] - i,ans[m * 2 - i]);
		while(s[i - ans[i]] == s[i + ans[i]]) ans[i] ++ ;
		if(ans[i] + i > m + ans[m])m = i;
		if(fans < ans[i])
		fans = ans[i];
	} 
	std::cout<<fans - 1;

迴文自動機