【URAL】1297 Palindrome【字符串--manacher算法】
阿新 • • 發佈:2018-10-16
n-1 imu 上網 har for pac .aspx 長度 鏈接
下標從0開始。
len數組表示以當前位置開始的 最長回文班級,其中# 不考慮。
所以上面例子的len數組如下圖所示。
傳送門:Palindrome
題意
求最長回文字符串,在學manacher算法,所以用了manacher,看到網上好多題解使用後綴數組來做的。
思路
manacher算法,參考《ACM國際大學生程序設計競賽 算法與實現》的板子,一開始我以為板子的manacher算法是錯誤的,然後上網看題解。
直到我看到 https://blog.csdn.net/u012717411/article/details/53363444 文章,我才知道其實人家是對的,只不過我沒理解。
manacher算法在O(N)的時間復雜度內求得了字符串所有子串的最長回文子串的長度。
例如輸入
abccba
最終的字符串會變成這樣 a#b#c#c#b#a
下標從0開始。
len數組表示以當前位置開始的 最長回文班級,其中# 不考慮。
所以上面例子的len數組如下圖所示。
至於manacher算法的原理,我大概理解,但還是不夠透徹。可以參考這篇文章。
https://blog.csdn.net/dyx404514/article/details/42061017
AC Code
/* 參考:https://blog.csdn.net/u012717411/article/details/53363444 算法過程: abccba -> a#b#c#c#b#a 下標從0開始。 #位置即(pos&1)==1 的位置 */ #include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=1e6+5; void manacher(char str[],int len[],int n) //接口 { len[0] = 1; for(int i = 1,j = 0; i < (n<<1) - 1; ++ i) { int p = i >> 1,q = i - p, r = ((j+1) >> 1) + len[j] - 1; len[i] = r < q?0:min(r-q+1,len[(j<<1) - i]); while(p > len[i] - 1 && q + len[i] < n && str[p - len[i]] == str[q+len[i]]) ++len[i]; if(q + len[i] - 1 > r) j = i; } } string longestPalindrome(string s) { int n = s.size(); /* len數組: */ int len[2000]; char *str = &s[0]; manacher(str,len,n);//調用接口,得到len[] for(int i=0;i<n*2;i++) { cout<<len[i]<<" "; } cout<<endl; string tmp = ""; int pos = 0,max_len = 0; for(int i = 0; i < (n<<1) - 1; ++ i) { //以‘#’or字符為中心,串長不一樣 int tmp_len = (i&1)?len[i]<<1:(len[i]<<1)-1; //pos記錄目標串的中心點,max_len表示目標串的串長(不含#) if(tmp_len > max_len) pos = i,max_len = tmp_len; //作一個tmp[0..2n-1]的字符串,便於輸出 if(i&1) tmp+="#"; else tmp+=s[i>>1]; } //# 為中心 if(pos&1) //找到要打印的串tmp的起始位置pos和打印長度max_len(便於打印輸出) { max_len = (len[pos] << 2) - 1; pos = pos - (len[pos] << 1) + 1; } else { max_len = (len[pos] << 2) - 3; pos = pos - ((len[pos]-1)<<1); } string ans = ""; for(int i = pos,j = 0; j < max_len; ++ j,++ i) { if(i&1) continue; ans+=tmp[i]; //tmp中找到所要打印的字符,鏈接起來 } return ans; } int main() { string s; cin>>s; cout<<longestPalindrome(s)<<endl; }
【URAL】1297 Palindrome【字符串--manacher算法】