manacher算法(求字符串最长回文子串/以某个点为中心的最长回文子串长度)


题目链接:https://ac.nowcoder.com/acm/contest/33540/A

此题为manacher算法的变形,利用了算法的一部分性质,还用到了差分求前缀和。

题目链接:https://www.luogu.com.cn/problem/P3805

此题纯为manacher的模板题;

题一代码:

 1 #include
 2 #include
 3 #include
 4 #include
 5 #include
 6 #include
 7 #include<set>
 8 #include
 9 #include
10 #include
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
 2 #include
 3 #include
 4 #include
 5 #include
 6 #include
 7 #include<set>
 8 #include
 9 #include
10 #include
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 }