1. 暴力
時間複雜度O(n^3)。
2. 延展
以某一字符爲中心,設置left, right兩個變量同時向外擴,判斷他們指向字符是否相同。注意分奇偶討論。時間複雜度O(n^2)。
3. Manacher 馬拉車
代碼註釋:
1 const int MAXN = 110009; 2 char ma[MAXN * 2]; //因爲要添加'#',所以長度要開兩倍 3 int mp[MAXN * 2]; 4 char s[MAXN]; 5 6 void Manacher(char s[], int len) { 7 8 // 1. 構造字符串,添加'#',使長度變爲奇數(2 * len - 1) 9 int l = 0; 10 ma[l++] = '$'; // 設置邊界 11 ma[l++] = '#'; 12 for(int i = 0; i < len; i ++) { 13 ma[l++] = s[i]; 14 ma[l++] = '#'; 15 } 16 ma[l] = 0; 17 18 // 核心: 求迴文半徑, 迴文半徑包括中心點 19 int mx = 0; // mx代表可達的最右值 20 int id = 0; // id代表mx的中心 21 for(int i = 0; i < l; i ++) { 22 mp[i] = mx > i ? min(mp[2 * id - i], mx - i) : 1; 23 while(ma[i + mp[i]] == ma[i - mp[i]]) { 24 mp[i] ++; 25 } 26 if(i + mp[i] > mx) { 27 mx = i + mp[i]; 28 id = i; 29 } 30 } 31 32 } 33 34 int main() 35 { 36 37 while(scanf("%s", s) != EOF) { 38 int len = strlen(s); 39 Manacher(s, len); 40 int ans = 0; 41 for(int i = 0; i < 2 * len + 2; i ++) { // 尋找最長的迴文半徑,即迴文串長度 42 ans = max(ans, mp[i] - 1); // 迴文半徑減1就是原迴文串的長度(迴文半徑中虛加了#) 43 cout << mp[i] << " "; 44 } 45 printf("%d\n", ans); 46 } 47 48 return 0; 49 }
時間複雜度O(n)。