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

两道题目涉及Manacher算法的使用,第一题通过变形处理字符串并利用差分求前缀和找到最长回文子串,第二题则直接应用Manacher算法模板找出最长回文子串。代码中包含字符串处理、回文判断和动态规划思想。
摘要由CSDN通过智能技术生成

题目链接: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 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值