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等
回文就是正反读都是一样的字符串,如aba, abba等
Input
输入有多组case,不超过120组,每组输入为一行小写英文字符a,b,c...y,z组成的字符串S
两组case之间由空行隔开(该空行不用处理)
字符串长度len <= 110000
两组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;}
阅读全文
0 0
- HDU 3068 ( 最长回文 )
- HDU-3068 最长回文
- hdu 3068 最长回文
- Hdu 3068 最长回文
- HDU 3068 最长回文
- HDU-3068-最长回文
- hdu-最长回文-3068
- hdu 3068 最长回文
- 【HDU】3068 最长回文
- hdu 3068 最长回文
- HDU 3068 最长回文
- hdu 3068 最长回文
- hdu 3068 最长回文
- hdu-3068-最长回文
- HDU 3068 最长回文
- HDU 3068 最长回文
- HDU 3068 最长回文
- HDU - 3068 最长回文
- BCC市值跃居第三,开始难度调整
- java中的断言
- HDU6148 Valley Numer (2017百度之星程序设计大赛
- BP神经网络JAVA实现详解
- /etc/fstab 参数详解及如何设置开机自动挂载
- HDU 3068 最长回文
- 1002(dp+树状数组+离散化)
- DialogViewpagerPhotoview显示大图
- Android5.1 Audio的FW和HAL层dump PCM数据
- 多线程
- Python dict
- 关于Vivado的SDK编译一直报错一些语法问题的解决
- SegmentFault 技术周刊
- CSU 1104 盒子游戏(博弈)