题目链接:
题目描述:
给出一串字符串代表暗码,暗码字符是通过明码循环移位得到的,比如给定b,就有b == a,c == b,d == c,.......,a == z。
问最长回文串所在区间,以及最长回文串所表示的明码。
解题思路:
字符串长度[1,200000],用manacher算法很轻松就搞定了。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 const int maxn = 400005; 7 char str[maxn]; 8 int p[maxn]; 9 int main () 10 { 11 int x, maxlen; 12 char s[2]; 13 while (scanf ("%s %s", s, str) != EOF) 14 { 15 memset (p, 0, sizeof(p)); 16 int len = strlen (str); 17 for (int i=len; i>=0; i--) 18 { 19 str[i*2+2] = str[i]; 20 str[i*2+1] = ‘#‘; 21 } 22 str[0] = ‘*‘;//str两端标志为不同字符,防止下标越界 23 x = maxlen = 0; 24 len = len * 2 + 1; 25 for (int i=2; i<len; i++) 26 { 27 if (p[x]+x > i) 28 p[i] = min (p[2*x-i], p[x]-i+x); 29 else 30 p[i] = 1; 31 while (str[i-p[i]] == str[i+p[i]]) 32 p[i] ++; 33 if (x+p[x] < i+p[i]) 34 x = i; 35 if (maxlen < p[i]) 36 maxlen = p[i]; 37 }//manacher模板 38 if (maxlen <= 2) 39 { 40 printf ("No solution!\n"); 41 continue; 42 } 43 int res = s[0] - ‘a‘, a, b; 44 for (int i=2; i<len; i++) 45 if (p[i] == maxlen) 46 { 47 //找到回文串所在区间 48 a = i - p[i] + 2; 49 b = i + p[i] - 2; 50 break; 51 } 52 printf ("%d %d\n", a/2-1, b/2-1); 53 for (int i=a; i<=b; i+=2) 54 { 55 str[i] -= res; 56 if (str[i] < ‘a‘) 57 str[i] += 26; 58 putchar(str[i]); 59 } 60 printf("\n"); 61 } 62 return 0; 63 }
Hdu 3294 Girls' research (manacher 最长回文串)
时间: 2024-10-05 01:32:27