1. 程式人生 > 其它 >manacher演算法(求字串最長迴文子串/以某個點為中心的最長迴文子串長度)

manacher演算法(求字串最長迴文子串/以某個點為中心的最長迴文子串長度)

題目連結:https://ac.nowcoder.com/acm/contest/33540/A

此題為manacher演算法的變形,利用了演算法的一部分性質,還用到了差分求字首和。

題目連結:https://www.luogu.com.cn/problem/P3805

此題純為manacher的模板題;

題一程式碼:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<vector>
 5 #include<map>
 6 #include<queue>
 7
#include<set> 8 #include<cmath> 9 #include<list> 10 #include<cstring> 11 #include<string> 12 #define ll long long 13 #define ull unsigned long long 14 #define inf 0x3f3f3f3f 15 #define inff 0x7fffffff 16 using namespace std; 17 const int N = 1000000 + 10; 18 19 int Len[N << 4
]; 20 21 int ans[N << 4]; 22 int b[N << 4]; 23 24 25 int longestPalindrome(string s) { 26 string new_str = ""; 27 new_str += "@"; 28 for (int i = 0; i < s.length(); i++) { 29 new_str += "#"; 30 new_str += s[i]; 31 } 32 new_str += "#"; 33 new_str += "
$"; 34 //cout << new_str << endl; 35 //new_str 儲存 擴充後的字串,如 @#a#b#a#$ 36 int len = new_str.length(); 37 int r = 0, mid = 0, ans = 0;//r 表示目前最右迴文子串半徑,mid則是該字串的中心下標,ans儲存最長迴文子串長度。 38 for (int i = 1; i < len - 1; i++) { 39 if (i < r) { 40 Len[i] = min(r - i, Len[2 * mid - i]); 41 } 42 else Len[i] = 1; 43 44 while (new_str[i + Len[i]] == new_str[i - Len[i]]) { 45 Len[i]++; 46 } 47 if ((i + Len[i]) > r) { 48 r = i + Len[i]; 49 mid = i; 50 } 51 ans = max(ans, (Len[i] - 1)); 52 } 53 return ans; 54 } 55 56 int main() { 57 58 int n; 59 cin >> n; 60 string s = ""; 61 for (int i = 0; i < n; i++) { 62 int x; 63 cin >> x; 64 s += (x + '0'); 65 } 66 int an = longestPalindrome(s); 67 68 /*for (int i = 0; i <= 2 * n + 1; i++) { 69 cout << Len[i] << " "; 70 } 71 cout << "\n";*/ 72 for (int i = 1; i <= 2 * n + 1; i++) { 73 int l = i - Len[i] + 1; 74 int r = i; 75 b[l] += 1; 76 b[r + 1] -= 1; 77 //QjUpdate(l, r, 1, 1, 2 * n + 1, 1); 78 //if (i % 2 == 0) cout << Query(i, i, 1, 2 * n + 1, 1) << " "; 79 } 80 for (int i = 1; i <= 2 * n + 1; i++) { 81 ans[i] = ans[i - 1] + b[i]; 82 if (i % 2 == 0) cout << ans[i] << " "; 83 } 84 /*for (int i = 2; i <= 2 * n; i += 2) { 85 cout << Query(i, i, 1, 2 * n + 1, 1) << " "; 86 }*/ 87 88 return 0; 89 }

題二程式碼:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<vector>
 5 #include<map>
 6 #include<queue>
 7 #include<set>
 8 #include<cmath>
 9 #include<list>
10 #include<cstring>
11 #include<string>
12 #define ll long long
13 #define ull unsigned long long
14 #define inf 0x3f3f3f3f
15 #define inff 0x7fffffff
16 using namespace std;
17 const int N = 11000000 + 10;
18 
19 int Len[N << 3];
20 
21 int longestPalindrome(string s) {
22     string new_str = "";
23     new_str += "@";
24     for (int i = 0; i < s.length(); i++) {
25         new_str += "#";
26         new_str += s[i];
27     }
28     new_str += "#";
29     new_str += "$";
30     //cout << new_str << endl;
31     //new_str 儲存 擴充後的字串,如 @#a#b#a#$
32     int len = new_str.length();
33     int r = 0, mid = 0, ans = 0;//r 表示目前最右迴文子串半徑,mid則是該字串的中心下標,ans儲存最長迴文子串長度。
34     for (int i = 1; i < len - 1; i++) {
35         if (i < r) {
36             Len[i] = min(r - i, Len[2 * mid - i]);
37         }
38         else Len[i] = 1;
39 
40         while (new_str[i + Len[i]] == new_str[i - Len[i]]) {
41             Len[i]++;
42         }
43         if ((i + Len[i]) > r) {
44             r = i + Len[i];
45             mid = i;
46         }
47         ans = max(ans, (Len[i] - 1));
48     }
49     return ans;
50 }
51 
52 int main() {
53 
54     string s;
55     cin >> s;
56     int an = longestPalindrome(s);
57     cout << an << "\n";
58 
59     return 0;
60 }