Manacher练习
K:
题意:求回文串。
思路:Manacher算法模版题
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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\n",t++,ans); 65 } 66 return 0; 67 }
L:
思路:在Manacher算法中判断是否增加回文长度的时候多判断下是否满足左边升序右边降序即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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\n", maxlen-1); 74 75 } 76 return 0; 77 }
M:
题意:输入格式 :字符(ch) +空格+字符串(s)。要先将s进行转换。ch要转换为'a',其他字符也要相应变化,比如ch='b'时。那么'b'就要转换为’a'。‘c'就要转换为 'b','d'要转换为'c',....,'a'要转换为'z'。简单来说,就要s中的每个字母要发生一定的偏移。题目要求转换后的s的最长回文子串的起始和终止位置,并输出子串,如果有多个则输出第一个。如果没有,就输出''No solution!''
思路:首先先对字符串进行转化,然后之后就是Manacher算法。这题的难点我觉得是在记录左右位置的地方。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }