Manacher练习

K:

题意:求回文串。

思路:Manacher算法模版题

 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <stdbool.h>
 5 #include <stdlib.h>
 6 #include <string>
 7 #include <string.h>
 8 #include <math.h>
 9 #include <vector>
10 #include <queue>
11 #include <stack>
12 #include <set>
13 #include <map>
14 
15 #define INF 0x3f3f3f3f
16 #define LL long long
17 #define MAXN 1000005
18 using namespace std;
19 
20 char Ma[MAXN*2];
21 int Mp[MAXN*2];
22 char s[MAXN];
23 
24 void Manacher(char s[],int len)
25 {
26     int l = 0;
27     Ma[l++] = '$';
28     Ma[l++] = '#';
29     for (int i=0;i<len;i++)
30     {
31         Ma[l++] = s[i];
32         Ma[l++] = '#';
33     }
34     Ma[l++] = 0;
35     int mx = 0;
36     int id = 0;
37     for (int i=0;i<l;i++)
38     {
39         Mp[i] = mx>i?min(Mp[2*id-i],mx-i):1;
40         while (Ma[i+Mp[i]] == Ma[i-Mp[i]])
41             Mp[i]++;
42         if (i+Mp[i]>mx)
43         {
44             mx = Mp[i]+i;
45             id = i;
46         }
47     }
48 }
49 
50 int main()
51 {
52     ios_base::sync_with_stdio(0);
53     cin.tie(NULL);
54     //freopen("../in.txt","r",stdin);
55     int t = 1;
56     while (cin >> s) {
57         if (strcmp(s,"END") == 0)
58             break;
59         int len = strlen(s);
60         Manacher(s, len);
61         int ans = 0;
62         for (int i = 0; i < 2 * len + 2; i++)
63             ans = max(ans, Mp[i] - 1);
64         printf("Case %d: %d
",t++,ans);
65     }
66     return 0;
67 }
Ackerman

L:

思路:在Manacher算法中判断是否增加回文长度的时候多判断下是否满足左边升序右边降序即可

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 #define ll long long int 
 8 #define ull unsigned long long int 
 9 #define e 2.718281828459
10 #define INF 0x7fffffff
11 #pragma warning(disable:4996)
12 #define pf printf
13 #define sf scanf
14 #define max(a,b) (a)>(b)?(a):(b);
15 #define min(a,b) (a)<(b)?(a):(b);
16 #define pi  acos(-1.0);
17 #define  eps 1e-9;
18 #include <cstdlib>
19 using namespace std;
20 
21 
22 
23 int n;
24 int ar[100005];
25 int temp[200010];
26 int p[200010];
27 int manacher(int len) {
28     int i, j ;
29     int mid=0;
30     int ans = 0;
31     int mx = 0;
32     p[0] = 1;
33     for (i = 1; i <= len; i++) {
34         j = 2 * mid - i;//j和i关于mid对称
35         if (i >= mx) p[i] = 1;//超出一位,一个字符,赋值1
36         else p[i] = min(p[j], mx - i);//二者中小的那一个,若 mx - i>p[j],说明i+回文长度未超过mx, mx - i<p[j],则说明i+p[i]回文长度超过了mx,回文只能取到mx-i然后手动匹配
37 
38                                       //不论超出与否,手动匹配,i超出或不超出都手动匹一下
39         while (temp[i - p[i]] == temp[i + p[i]]&&temp[i+p[i]-2]>=temp[i+p[i]])// i - p[i]>=1&&i+p[i]<=len 被省去,因为temp[0]和temp[len]不同
40             p[i]++;
41 
42         if (i + p[i] > mx) {
43             mx = i + p[i];//更新mx让它尽量远移
44             mid = i;//更新中点mid
45         }
46         ans=ans > p[i] ? ans : p[i];//记录最大回文长度
47     }
48 
49 
50     return ans;
51 }
52 
53 void init(int len) {
54     temp[0] = -1;//第一位加-1防止溢出
55     temp[1] =-1;
56     int i,j;
57 
58     for (i = 2, j = 0; j < len; j++) {
59         temp[i++] = ar[j];
60         temp[i++] = -1;
61     }
62     temp[i] = -2;//最后一位防止溢出,注意要和第一位的值不同,这样在匹配时才可省去溢出判断
63 }
64 
65 int main(void) {
66     int t;
67     sf("%d", &t);
68     while (t--) {
69         sf("%d",&n);
70         for (int i = 0; i < n; i++)  sf("%d", &ar[i]);
71         init(n);
72         int maxlen = manacher(2 * n + 1);//2*n+1:除去最头和最尾
73         pf("%d
", maxlen-1);
74 
75     }
76     return 0;
77 }
Ackerman

M:

题意:输入格式 :字符(ch) +空格+字符串(s)。要先将s进行转换。ch要转换为'a',其他字符也要相应变化,比如ch='b'时。那么'b'就要转换为’a'。‘c'就要转换为 'b','d'要转换为'c',....,'a'要转换为'z'。简单来说,就要s中的每个字母要发生一定的偏移。题目要求转换后的s的最长回文子串的起始和终止位置,并输出子串,如果有多个则输出第一个。如果没有,就输出''No solution!''

思路:首先先对字符串进行转化,然后之后就是Manacher算法。这题的难点我觉得是在记录左右位置的地方。

 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <stdbool.h>
 5 #include <stdlib.h>
 6 #include <string>
 7 #include <string.h>
 8 #include <math.h>
 9 #include <vector>
10 #include <queue>
11 #include <stack>
12 #include <set>
13 #include <map>
14 
15 #define INF 0x3f3f3f3f
16 #define LL long long
17 #define MAXN 200005
18 using namespace std;
19 
20 char Ma[MAXN*2];
21 int Mp[MAXN*2];
22 char s[MAXN];
23 int cnt;
24 int middle;
25 
26 void Manacher(char s[],int len)
27 {
28     cnt = 0;
29     int l = 0;
30     Ma[l++] = '$';
31     Ma[l++] = '#';
32     for (int i=0;i<len;i++)
33     {
34         Ma[l++] = s[i];
35         Ma[l++] = '#';
36     }
37     Ma[l++] = 0;
38     int mx = 0;
39     int id = 0;
40     for (int i=0;i<l;i++)
41     {
42         Mp[i] = mx>i?min(Mp[2*id-i],mx-i):1;
43         while (Ma[i+Mp[i]] == Ma[i-Mp[i]])
44             Mp[i]++;
45         if (i+Mp[i]>mx)
46         {
47             mx = Mp[i]+i;
48             id = i;
49         }
50         if (Mp[i]-1>cnt){
51             cnt = Mp[i]-1;
52             middle = i;
53         }
54     }
55 }
56 
57 int main()
58 {
59     ios_base::sync_with_stdio(0);
60     cin.tie(NULL);
61     char c;
62     while (cin >> c)
63     {
64         middle = 0;
65         cin >> s;
66         int len = strlen(s);
67         int dis = c-'a';
68         for (int i=0;i<len;i++)
69         {
70             s[i] = (s[i]-'a'-dis+26)%26+'a';
71         }
72         Manacher(s,len);
73         if (cnt == 1)
74             cout << "No solution!" << endl;
75         else
76         {
77             int l = middle-cnt+1;
78             int r = middle+cnt-1;
79             cout << l/2-1 << " " << r/2-1 << endl;
80             for (int i=l;i<=r;i++)
81             {
82                 if (Ma[i] == '#' || Ma[i] == '$')
83                     continue;
84                 else
85                     cout << Ma[i];
86             }
87             cout << endl;
88         }
89     }
90     return 0;
91 }
Ackerman
原文地址:https://www.cnblogs.com/-Ackerman/p/11286191.html