Girls' researchTime Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 4365 Accepted Submission(s): 1633 Problem Description One day, sailormoon girls are so delighted that they intend to research about palindromic strings. Operation contains two steps: Input Input contains multiple cases. Output Please execute the operation following the two steps. Sample Input b babd a abcd Sample Output 0 2 aza No solution! |
题意:要你找出最长回文串的开头和结尾,并且要遵守如下规则将最长公共子串变形输出:开始会给你一个即将代替a的的字符,如样例中的b,变成a,则c就是b,....a就是z。
做法:没什么好解释的就是板子套套的事情,注意中间的转化就好。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int maxn=200010;
char str[maxn];//原字符串
char tmp[maxn<<1];//转换后的字符串
int Len[maxn<<1],mx,po,ans,ansst,ansen,anslen;
char fi[5],s[maxn];
int init(char *st){//转换原始串
int i,len=strlen(st);
tmp[0]='@';//字符串开头增加一个特殊字符,防止越界
for(i=1;i<=2*len;i+=2){
tmp[i]='#';
tmp[i+1]=st[i/2];
}
tmp[2*len+1]='#';
tmp[2*len+2]='$';//字符串结尾加一个字符,防止越界
tmp[2*len+3]=0;
return 2*len+1;//返回转换字符串的长度
}//Manacher算法计算过程
int Manacher(char *st,int len){
mx=0,ans=0,po=0;//mx即为当前计算回文串最右边字符的最大值
for(int i=1;i<=len;i++){
if(mx>i)
Len[i]=min(mx-i,Len[2*po-i]);//在Len[j]和mx-i中取个小
else
Len[i]=1;//如果i>=mx,要从头开始匹配
while(st[i-Len[i]]==st[i+Len[i]])
Len[i]++;
if(Len[i]+i>mx){//若新计算的 回文串右端点位置大于mx,要更新po和mx的值
mx=Len[i]+i;
po=i;
}
if(ans<Len[i]){
if(i%2==0) ansst=i/2-(Len[i]-1)/2,ansen=i/2+(Len[i]-1)/2;
else { ansst=(i-1)/2-(Len[i]-1)/2+1,ansen=(i-1)/2+(Len[i]-1)/2;}
anslen=ansen-ansst;
ans=Len[i];
}
}
return ans-1;//返回Len[i]中的最大值-1即为原串的最长回文子串额长度
}
int main(){
while(~scanf("%s%s",fi,s)){
int len=init(s);
int ans=Manacher(tmp,len);
if(ans==1) printf("No solution!\n");
else {
ansst--,ansen--;
int cha=fi[0]-'a';
printf("%d %d\n",ansst,ansen);
for(int i=ansst;i<=ansen;i++){
printf("%c",(s[i]-'a'+26-cha)%26+'a');
}
cout<<endl;
}
}
return 0;
}