题意:给一个字母ch和一个只包含小写字母的串,用字母'a'代替串中出现的ch,用字母'b'代替字母表中ch后面的一个字母,'c'代替ch后面第二个字母,以此类推。。。相当于在原串的基础上做一个映射。求出最长回文串的起点和终点,如果最长回文串长度小2就输出无解。如果有多解就输出第一个。
思路:先把串按题目说的搞一下,然后Manacher即可。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int mod = 1000000007;
const int maxn = 200005;
int pos, maxlen, st;
int manacher(char s[], char str[], int p[]){
int len = strlen(s);
str[0] = '*';
for(int i = 0; i <= len; ++i){
str[i * 2 + 1] = '#';
str[i * 2 + 2] = s[i];
}
len = 2 * len + 1;
pos = 0, maxlen = 1;
p[0] = 1;
for(int i = 2; i < len; ++i){
if(i < p[pos] + pos){
p[i] = min(pos + p[pos] - i, p[pos * 2 - i]);
} else {
p[i] = 1;
}
while(str[i - p[i]] == str[i + p[i]]){
++p[i];
}
if(i + p[i] > pos + p[pos]){
pos = i;
}
if(p[i] > maxlen){
maxlen = p[i];
st = i;
}
}
return maxlen - 1;
}
char s[maxn], str[maxn * 2];
int p[maxn * 2];
int main(){
char ch;
while(~scanf("%c%s", &ch, s)){
getchar();
int len = strlen(s);
int tmp = ch - 'a';
for(int i = 0; i < len; ++i){
s[i] = 'a' + (s[i] - 'a' - tmp + 26) % 26;
}
if(manacher(s, str, p) < 2){
puts("No solution!");
} else {
st = (st - maxlen) / 2;//起点
int en = st + maxlen - 2;//终点
printf("%d %d\n", st, en);
for(int i = st; i <= en; ++i){
putchar(s[i]);
}
putchar('\n');
}
}
return 0;
}