HDU 3068 最长回文

来源:互联网 发布:淘宝卖家客服常用语 编辑:程序博客网 时间:2024/06/03 18:54

最长回文

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 23719    Accepted Submission(s): 8673

Problem Description
给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度.
回文就是正反读都是一样的字符串,如aba, abba等

Input
输入有多组case,不超过120组,每组输入为一行小写英文字符a,b,c...y,z组成的字符串S
两组case之间由空行隔开(该空行不用处理)
字符串长度len <= 110000

Output
每一行一个整数x,对应一组case,表示该组case的字符串中所包含的最长回文长度. 

Sample Input
aaaaabab
 
Sample Output
43

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3068

题意:如题。

解题思路:今天学了一个好东西,叫做Manacher算法,用来查找最长回文,下面呢,我试着说一下它的思想,能不能说清楚是另外一件事啦,哈哈。

首先这个算法有很多好处:

1、它解决了字符串长度的奇偶带来的不便,奇偶性不影响它的计算。

2、它在时间复杂度上面比朴素算法优秀太多。

核心:

1、将输入的字符串S其尾每两个相邻的字符串中间插入一个无关字符,何为无关字符,就是在原字符串中没有出现的字符,此题中以#为例。例如:abab变为#a#b#a#b#。(解决了对称轴的奇偶性)

2、P[]数组,P[i]表示插入无关字符后的以S[i]为对称轴的回文字符串的半径。

其实只要得到了P数组,那么最后扫描一遍P数组找到最大的回文串长度输出就好,那么现在的关键就是如何高效地求解P数组。P数组的求解有点类似扩展KMP求extend数组。max_right为匹配到达的最右位置,pos为此次匹配的对称轴,当现在要求P[i]时,如果i<max_right,我们知道P[pos*2-max_rigtht...pos-1]=P[pos+1...max_right]。现在i<max_right,那么我们知道以P[i]=max(P[pos*2-i],max_right)。如果i>=max_right,那么P[i]=1,再根据P[i]的值开始向两边扩展匹配,记得更新max_right和pos,P[i]-1就是原字符串的回文长度(具体可以自己画图或者参考大佬关于该算法的详细介绍

AC代码:

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int MAXL = 110000 + 10; //字符串的最长长度 char str[MAXL]; //字符数组 char S[2*MAXL]; //插入无关字符后的数组 int P[2*MAXL]; //记录每个字符作为回文对称轴的最长回文半径 void init() //初始化S {memset(S,'\0',sizeof(S)); S[0]='#'; //起始位置插入无关字符 int i,j; for(i=0,j=1;str[i]!='\0';i++) //相邻字符之间插入 {S[j++]=str[i];S[j++]='#';}S[j]='\0';}void getP() //得到P数组 {memset(P,0,sizeof(P));int pos=0; //匹配最右的对称轴 int max_right=0; //匹配的最右位置 for(int i=1;S[i]!='\0';i++) //获得每个字符作为对称轴的回文半径 {if(max_right>i) P[i]=min(P[2*pos-i],max_right-i); //i小于max_right else P[i]=1;//i大于max_right for(;i-P[i]>=0 && S[i-P[i]]==S[i+P[i]];P[i]++) ; //根据P[i]的值开始左右匹配 if(i+P[i]>max_right) //更新max_right和pos {max_right=i+P[i];pos=i;}}}void solve(){init(); //初始化函数 getP(); //获到P数组 int ans=0;for(int i=1;S[i]!='\0';i++){ans=max(ans,P[i]-1); //最大的回文串长度 }printf("%d\n",ans); }int main(void){while(scanf("%s",str)==1) //输入字符串 {solve(); //处理函数 }return 0;}





原创粉丝点击