時間限制:1000ms
單點時限:1000ms
記憶體限制:64MB
描述
小Hi和小Ho是一對好朋友,出生在資訊化社會的他們對編程產生了莫大的興趣,他們約定好互相協助,在編程的學習道路上一同前進。
這一天,他們遇到了一連串的字串,於是小Hi就向小Ho提出了那個經典的問題:“小Ho,你能不能分別在這些字串中找到它們每一個的最長迴文子串呢。”
小Ho奇怪的問道:“什麼叫做最長迴文子串呢。”
小Hi回答道:“一個字串中連續的一段就是這個字串的子串,而迴文串指的是12421這種從前往後讀和從後往前讀一模一樣的字串,所以最長迴文子串的意思就是這個字串中最長的身為迴文串的子串啦~”
小Ho道:“原來如此。那麼我該怎麼得到這些字串呢。我又應該怎麼告訴你我所計算出的最長迴文子串呢。
小Hi笑著說道:“這個很容易啦,你只需要寫一個程式,先從標準輸入讀取一個整數N(N<=30),代表我給你的字串的個數,然後接下來的就是我要給你的那N個字串(字串長度<=10^6)啦。而你要告訴我你的答案的話,只要將你計算出的最長迴文子串的長度按照我給你的順序依次輸出到標準輸出就可以了。你看這就是一個例子。”
提示一 提示二 提示三 提示四
範例輸入
3
abababa
aaaabaa
acacdas
範例輸出
7
5
3
這一道題目的關鍵:
1、是採用Manacher演算法來進行求解最長迴文字串,時間複雜度為O(N)。
2、本題目在資料最大時候可以達到1000000。所以為了防止構造新的字串時候浪費大量時間所以我們對數組進行預先分配記憶體。
#include<iostream>#include<string>#include<algorithm>using namespace std;static string afterProcessStr(1000002*2,'#');//預先分配記憶體並進行初始化int preprocess(string &str)//預先處理時候只要把奇數位置的‘#’替換了就好。{ //string afterProcessStr="#"; for(int i=0;i<str.size();++i) { afterProcessStr [2*i+1]= str[i]; } return str.size()*2+1; //afterProcessStr.clear();}int maxpalindrome(string &str){ int sizeStr=preprocess(str); // cout<<afterProcessStr<<endl; int maxEdge=0,center=0; int *p=new int[sizeStr](); int ans=0; for(int i=1;i<sizeStr;++i) { p[i]=(maxEdge>i)?min(maxEdge-i,p[2*center-i]):0; while(i-1-p[i]>=0&&i+1+p[i]<sizeStr&&afterProcessStr[i+1+p[i]]==afterProcessStr[i-1-p[i]]) ++p[i]; if(i+p[i]>maxEdge) { center=i; maxEdge=i+p[i]; } if(p[i]>ans) ans=p[i]; } return ans;}int main(){ int tn; cin>>tn; string str; str.reserve(1000002); int ans,tmp; for(int ye=0;ye<tn;++ye) { cin>>str; cout<<maxpalindrome(str)<<endl; }}