Hdu 3294 Girls' research (manacher 最长回文串)
题目链接:
题目描述:
给出一串字符串代表暗码,暗码字符是通过明码循环移位得到的,比如给定b,就有b == a,c == b,d == c,.......,a == z。
问最长回文串所在区间,以及最长回文串所表示的明码。
解题思路:
字符串长度[1,200000],用manacher算法很轻松就搞定了。
1 #include <cstdio> 2 #include <string> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 #include <cmath> 7 #include <queue> 8 using namespace std; 9 10 typedef long long LL; 11 const int maxn = 410010; 12 char a[maxn], b[maxn*2]; 13 int vis[maxn*2]; 14 15 void manacher (char s[], int len) 16 { 17 int l = 0; 18 b[l ++] = '$'; 19 b[l ++] = '#'; 20 for (int i=0; i<len; i++) 21 { 22 b[l ++] = s[i]; 23 b[l ++] = '#'; 24 } 25 b[l] = 0; 26 27 /** 28 vis[i],以i为中心的回文串,向两端延伸的长度 29 mx为向后延伸最长的回文串延伸到的位置,id为其中心 30 31 **/ 32 33 int mx = 0, id = 0, ans = 0, index; 34 for (int i=0; i<l; i++) 35 { 36 37 /** 38 i < mx,因为[id-vis[id],mx],所以i与id-(i-id)对称 39 当i+vis[2*id-i] > mx时,vis[i] = mx - i; 40 41 当i >= mx....... 42 43 两端字符匹配时增加vis[i] 44 45 更新id 和 mx 46 **/ 47 48 vis[i] = mx > i ? min (vis[2*id-i], mx-i) : 1; 49 while (b[i+vis[i]] == b[i-vis[i]]) vis[i] ++; 50 if (i + vis[i] > mx) 51 { 52 mx = i + vis[i]; 53 id = i; 54 } 55 if (ans < vis[i]) 56 { 57 ans = vis[i]; 58 index = i; 59 } 60 } 61 62 /** 63 每一个回文串都是以'#'为边界 64 vis[i]是以i为第一个字母,向两边延伸的长度 65 每一个字母在b数组中的偶数位置 66 **/ 67 68 int x = index - vis[index] + 2; 69 int y = index + vis[index] - 2; 70 x = x / 2 - 1; 71 y = y / 2 - 1; 72 if (y != x) 73 { 74 printf ("%d %d\n", x, y); 75 for (int i=x; i<=y; i++) 76 printf ("%c", a[i]); 77 printf ("\n"); 78 } 79 else 80 printf ("No solution!\n"); 81 } 82 83 int main () 84 { 85 char ch[2], vis[30]; 86 while (scanf ("%s %s", ch, a) != EOF) 87 { 88 int n = strlen (a); 89 90 for (int i=0; a[i]; i++) 91 { 92 a[i] -= ch[0] - 'a'; 93 if (a[i] < 'a') 94 a[i] += 26; 95 } 96 97 manacher(a, n); 98 } 99 return 0; 100 }
本文为博主原创文章,未经博主允许不得转载。