作为一名情报工作人员,你现在需要破解一段只由小写字母组成的密文,密文到原文的破解规则如下:
将每个字母破解成它们在字母表中 x 个字母之前的字母(将字母表视为一个环)。例如:若 x=1,则 b 应破解成 a,a 应破解成 z,z 应破解成 y,以此类推。
密文中有大量的为加密而设计的无效信息,真正的有效信息是密文中出现的第一个最长回文。
现在给你一段密文,和这段密文在解密时哪个字母应该被破解为 a,请你破解出这段密文的有效信息,有效信息的长度至少应为 2,否则就认为这段密文无效,输出 “No solution!”。
Tips: 回文是指左右对称的字符串,如 abcba。
标准输入
输入包含多组数据,请一直处理到 EOF。
每组数据仅包括一行:
一个小写字母,表示哪个字母应破解为 a,紧接着一个字符串,表示密文。密文长度不超过 200000。
标准输出
对于每组数据:
如果破解出的有效信息长度 >= 2,则输出两行,第一行输出两个整数,表示你所破解出的有效信息在原始密文中的起始位置和结束位置(下标从0开始计算),第二行输出一个字符串,表示破解出的有效信息。
如果破解出的有效信息长度 < 2,说明密文无效,输出 “No solution!”。
样例输入
b babad
a abcd
样例输出
0 2
aza
No solution!
样例解释
对于第一组样例:
由于破解时 b 破解为 a,由此可以推出 a 应破解为 z,d 应破解为 c,因此由密文破解出的原文为 azazc,这之间的最长回文有两个,分别为 aza 和 zaz,但 aza 更先出现,因此最终破解出的有效信息的起始和结束位置为 0 和 2,内容为 aza。
对于第二组样例:
由于破解时 a 破解为 a,所以可以推出原文为 abcd,由于在原文中没有长度在 2 以上的回文,因此密文无效,输出 No solution!
思路:马拉车模板就是需要一些判断,首先判断一下是否存在一个大于等于2的回文串,有的话找到最长的并且最早出现的位置,因为我们已经把每一个回文串的长度记录了所以遍历一遍就可以了,最后就是找他的起始和终点位置
比如一个串为:##a#b#b#a0,它最长的回文串是以第四个#为回文中心,字母除2-1就是它再原始串的位置,假设#的位置为i那么旁边字母在原始串中的位置为(i-1)/2-1,(i+1)/2-1,然后我们知道回文串的总长度除以二算出来一个方向有多少字母我们就可以求出在原始串中回文串的起始位置和终点位置了
我们设d=(p[i]-1)/2,则st=(i-1)/2-(d-1)-1,end=(i+1)/2+(d-1)-1;
如果最长回文串的回文中心是个字母推的方法类似 st=(i/2)-(p[i]-2)/2-1;end=(i/2)+(p[i]-2)/2-1;
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
char len[N],s[N];
int p[N],l,L;
void init()
{
int k=0,kk;
len[k++]='#';
for(int i=0;i<l;i++)
{
len[k++]='#';
len[k++]=s[i];
}
len[k++]='#';
len[k]=0;
L=k;
}
int mach()
{
int id=0,mx=0,maxx=-1,i;
for(i=1;i<L;i++)
{
if(mx>i) p[i]=min(p[2*id-i],mx-i);
else p[i]=1;
while(len[i+p[i]]==len[i-p[i]])
{
p[i]++;
}
if(i+p[i]>mx)
{
id=i;
mx=i+p[i];
}
maxx=max(maxx,p[i]);
}
return maxx-1;
}
int main()
{
char c;
while(~scanf("\n%c %s",&c,s))
{
memset(p,0,sizeof(p));
//memset(len,'\0',sizeof(len));
l=strlen(s);
init();
int t=mach();
if(t<2)//判断是否存在大于等于2的回文串
{
printf("No solution!\n");
continue;
}
else
{
int y=c-97;
for(int i=1;i<L;i++)
{
if(p[i]-1==t)//找到最早出现的最长回文串
{
if(len[i]=='#')
{
int d=(p[i]-1)/2;
int st=(i-1)/2-(d-1);
int end=(i+1)/2+(d-1);
printf("%d %d\n",st-1,end-1);
for(i=st-1;i<=end-1;i++)
{
if(s[i]-y>=97)
{
printf("%c",s[i]-y);
}
else
{
printf("%c",'z'-(97-(s[i]-y)-1));
}
}
printf("\n");
}
else
{
int st=(i/2)-(p[i]-2)/2;
int end=(i/2)+(p[i]-2)/2;
printf("%d %d\n",st-1,end-1);
for(i=st-1;i<=end-1;i++)
{
if(s[i]-y>=97)
{
printf("%c",s[i]-y);
}
else
{
printf("%c",'z'-(97-(s[i]-y)-1));
}
}
printf("\n");
}
break;
}
}
}
}
}