题目大意:输入一个字符ch和一个字符串,问如果把ch当作'a'的话,字符串的每个字符也要做相应变化,如b aa,若b为'a',则b前面的a就为'a'前面的'z',这里是循环表示,输出字符串的最长回文子串,如果最长回文子串串长为1,输出No solution!
题目分析:字符串根据要求变换一下,跑一次Manacher,每次更新maxl时,分别记录左右端点在原串中的位置
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int const MAX = 200005;
char s[MAX << 1], save[MAX << 1];
int p[MAX << 1], l, r;
int Manacher()
{
int len = strlen(s), maxp = 0, maxl = 0;
for(int i = len; i >= 0; i--)
{
s[i * 2 + 2] = s[i];
s[i * 2 + 1] = '#';
}
s[0] = '*';
for(int i = 2; i < 2 * len + 1; i++)
{
if(p[maxp] + maxp > i)
p[i] = min(p[2 * maxp - i], p[maxp] + maxp - i);
else
p[i] = 1;
while(s[i - p[i]] == s[i + p[i]])
p[i]++;
if(p[maxp] + maxp < i + p[i])
maxp = i;
if(maxl < p[i])
{
l = (i - p[i]) / 2;
r = (i + p[i]) / 2 - 2;
maxl = p[i];
}
}
return maxl - 1;
}
int main()
{
int ans;
char ch[2];
while(scanf("%s %s",ch, s) != EOF)
{
int len = strlen(s);
l = r = 0;
for(int i = 0; i < len; i++)
{
int tmp = s[i] - ch[0];
if(tmp < 0)
tmp = 26 + tmp;
s[i] = 'a' + tmp;
}
strcpy(save, s);
int ans = Manacher();
if(ans == 1)
printf("No solution!\n");
else
{
printf("%d %d\n", l, r);
for(int i = l; i <= r; i++)
printf("%c", save[i]);
printf("\n");
}
}
return 0;
}