传送门

题目大意:输入一个字符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;
}