Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 1027 Accepted Submission(s): 389
题意:求最长回文子串,并求出起始位置。
分析:预处理移位表,之后用Manacher算法搞定
转载请注明出处:寻找&星空の孩子
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3294
//Manacher算法
#include
#include
#include
using namespace std;
#define maxn 200010*2
int P[maxn];
//(p.s. 可以看出,P[i]-1正好是原字符串中回文串的总长度)
char s1[maxn];
char s2[maxn];
char ch[30];
void manacher(char* s)
{
int i,id=0,mx=0;
P[0]=0; //P[0]位置没用
for(i=1;s[i];i++) //对串进行线性扫描
{
if(mx > i) //如果mx比当前i大,分为两种情况,详细致请看文章开头推荐的blog上的图示,非常给力的图
P[i] = min(P[2*id-i],mx-i);
else //如果mx比i小,没有可以利用的信息,那么就只能从头开始匹配
P[i] = 1;
while(s[i+P[i]]==s[i-P[i]] )P[i]++; //匹配
if(mx < P[i] + i) //坚持是否有更新mx以及id
{
mx = P[i] + i;
id = i;
}
}
}
void init(int t)
{
int i, j = 2;
s2[0] = '$', s2[1] = '#';
for(i=0;s1[i];i++)
{
s2[j++] = s1[i];
s2[j++] = '#';
}
s2[j] = '\0';
//置换表
char ex='a';
ch[t]=ex++;
for(i=t+1;(i%26)!=t;i++)
{
ch[i%26]=ex++;
}
// for(i=0;i<=25;i++)
// printf("%c",ch[i]);
}
int main()
{
char gh,gg;
while(scanf("%c %s%c",&gh,s1,&gg)!=EOF)
{
// getchar();
init(gh-'a');
manacher(s2);
int ans=0,x,y;
for(int i=1;s2[i]!='\0';i++)
{
if(P[i]>ans)
{
ans=P[i];
x=i;
}
}
//printf("%d\n",ans-1);
if(ans-1==1) {printf("No solution!\n");continue;}
// printf("ans=%d\tx=%d\n",ans,x);
// if(x&1){x=(x-1)/2;x=x-(ans-1)/2;y=x+ans-2;}
// else {x=(x-1)/2;x=x-(ans-1)/2;y=x+ans-2;}
//对应起始终点位置
x=(x-1)/2;
x=x-(ans-1)/2;
y=x+ans-2;
printf("%d %d\n",x,y);
for(int i=x;i<=y;i++)
{
printf("%c",ch[s1[i]-'a']);
}
printf("\n");
}
return 0;
}
/*
a abbab
a abbabcba
b babd
a abcd
*/