题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3294
题目大意:输入一个字符ch和一个字符串,问如果把ch当作‘a‘的话,字符串的每个字符也要做相应变化,如b aa,若b为‘a‘,则b前面的a就为‘a‘前面的‘z‘,这里是循环表示,输出字符串的最长回文子串,如果最长回文子串串长为1,输出No solution!
几乎是模板题,唯一的特别之处就是要输出回文串字符,所以要记录max(Mp[i])对应的在原串中的字符区间,根据Manacher算法的步骤逆推即可,所以要对算法的基础步骤要熟练,毕竟是简单的算法。
//171MS 2536K #include<cstdio> #include<iostream> #include<cstring> #define M 200100 using namespace std; int Mp[M<<1]; char s[M],Ma[M<<1]; int maxn,L,R; void Manacher(char s[],int len) { int l=0; Ma[l++]='$'; Ma[l++]='#'; for(int i=0;i<len;i++){ Ma[l++]=s[i]; Ma[l++]='#'; } Ma[l]=0; int mx=0,id=0; for(int i=1;i<l ;i++){ Mp[i]= mx>i? min(Mp[2*id-i],mx-i) :1; while(Ma[Mp[i]+i ]==Ma[i-Mp[i] ]) Mp[i]++; if(Mp[i]+i>mx){ mx=Mp[i]+i; id=i; } if(Mp[i]-1>maxn){ maxn=Mp[i]-1; L = (i-Mp[i])>>1; //根据对原串的处理逆推 R = (i+Mp[i]-4)>>1; //根据对原串的处理逆推 } } } int main () { char a[5]; while(~scanf("%s%s",a,s)){ maxn=-1; int len=strlen(s); Manacher(s,len); if(maxn==1) printf("No solution!"); else { printf("%d %d\n",L,R); for(int i=L;i<=R;i++){ printf("%c",'a'+((s[i]-a[0])+26)%26); //小技巧,把值循环圈定在26个字母范围内 } } puts(""); } return 0; }
HDU 3294 Girls' research (Manacher算法 + 记录区间)
时间: 2024-12-27 10:16:33