先把字符串转换一下,然后求mp[]。
加了其他字符后,2k ,k = 1,2,…的位置实际上是原来的k/2-1的字符。
所以求得最长半径r和对应位置pos后,
对应的原数组下标就是[(pos-r+1)/2 -1,(pos+r-1)/2-1],一边加一边减是因为加入新字符后回文字串的最外层一定是特殊字符
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
char s1[2],s2[202020],ma[404040];
int ans,pos,mp[404040];
void manacher(int len){
int l = 0;
ma[l++] = '$';
ma[l++] = '%';
for(int i = 0;i<len;i++){
ma[l++] = s2[i];
ma[l++] = '%';
}
int id = 0,mx= 0;
for(int i = 0;i<l;i++){
mp[i] = mx>i?min(mp[2*id-i],mx-i):1;
while(ma[i-mp[i]]==ma[i+mp[i]]) mp[i]++;
if(i+mp[i]>mx){
mx = i+mp[i];
id = i;
}
}
}
int main(){
while(~scanf("%s%s",s1,s2)){
int dif = s1[0] - 'a',len = strlen(s2);
ans = 0;
for(int i =0;i<len;i++)
s2[i] = (s2[i]-'a'-dif+26)%26+'a';
manacher(len);
for(int i = 0;i<2*len+2;i++){
if(mp[i]-1>ans) {
ans = mp[i] -1;
pos = i ;
}
}
if(ans == 1) printf("No solution!\n");
else {
printf("%d %d\n",(pos-ans+1)/2-1,(pos+ans-1)/2-1);
for(int i = (pos-ans+1)/2-1;i<=(pos+ans-1)/2-1;i++)
printf("%c",s2[i]);
printf("\n");
}
}
return 0;
}