最长回文串
来源:互联网 发布:专业淘宝拍摄 编辑:程序博客网 时间:2024/05/01 14:45
(1)思路
1. 因为字符串长度为奇数和偶数时处理方式不同,所以这里可以使用插入特殊字符的方法,使得每个字符串在处理之后长度都为奇数。处理方法为:在任意两个字符之间和字符串的开始和结尾插入'#'。(因为设字符为n个,那么共有n-1个间隙,n+(n-1)必然为奇数,再加上首尾'#'还是奇数)。因为要防止越界,所以在修改后的字符串首尾再加上边界,开始为'$',结尾为'@'
private String chuli(String str) {StringBuffer sb = new StringBuffer();sb.append('$'); //加入开始标识for(int i=0; i<str.length(); i++){sb.append('#'); //每个字符之前加入#sb.append(str.charAt(i));}sb.append('#'); //末尾加入#sb.append('@'); //加入结束符return sb.toString();}测试:
String str = "abba";str = chuli(str);for(int i=0; i<str.length(); i++)System.out.print(str.charAt(i)+" ");
结果为:
$ # a # b # b # a # @2. 核心算法
1>定义数组p[i]:表示以str[i]为中心的最大回文串的长度(包含字符str[i]),pi表示已经求得的拥有最长回文串的字符的下标,mx表示最长回文串所能达到的最右边的边界
2>
pi是最长回文串的中心(淡蓝色),如果以j为中心的最大回文串如上图所示,那么处于i处的情况和j处相同(因为pi的两侧是对称的)。这样求i的时候就可以利用j的结果了,此处显然j = 2*pi-i
mx是最长回文串的右边界,因为i<mx所以在求p[i],即以i为中心的回文串时,就可以利用关于pi的对称点j的信息。因为图中蓝色标志长度相同,均为mx-i,所以当mx-i>p[j],即图中所示情况时,p[i] = p[j],其余能不能再延长,就只能一个个字符判断了。
3>
这种情况虽然mx>i,但是mx-i<p[j],也就是说最长回文串并没有全部包含以j为中心的回文串,所以此处最长只能选择mx-i为半径,即p[i] = mx-i
4>最后一种情况:mx-i<0,即i在最长回文串的外面,所以此时就只能从头开始算了,即p[i] = 1
(2)代码
@Testpublic void huiwen(){String str = "abba";str = chuli(str);int mx = 0;int pi = 1;int[] p = new int[str.length()];for(int i=1; i<str.length(); i++) //因为已经将字符串第0个字符设置为$,所以直接从第1个开始{if(mx>i) //如果i在mx内,即可以利用以前求得的结果{if(mx-i>p[pi*2-i]) //整个i的对称点j = pi*2-i,都在最长回文串中p[i] = p[pi*2-i];else //一部分在最长回文串外p[i] = mx-i;}else //因为i在mx外,所以不能利用之前求得的结果,那么就直接设为1p[i] = 1;while(i-p[i]>0 && i+p[i]<str.length() && str.charAt(i+p[i])==str.charAt(i-p[i])) //设置完p[i]的初始值之后,再一次扩展两边,看看是 //否能够将回文串扩大p[i]++;if(mx<i+p[i]) //如果当前求得的回文串长度大于之前最大的,那么更新最大值{mx = i+p[i]-1; //i+p[i]-1为右边界pi = i;}}int maxLen = p[0];for(int i=1; i<p.length; i++) //选出其中最长的半径maxLen = Math.max(maxLen, p[i]);System.out.println(maxLen-1); //maxLen-1就是原字符串的最大回文串长度,下面证明}
(3)注意
1.因为p[i]记录的是插入分隔符之后的回文串的半径,所以以i为中心的回文串的长度为2*p[i]-1.如bb->$#b#b#@,中间#的半径为3,所以回文串长度为2*3-1 = 5
2.因为#b#b#长度-1后,就正好是原来字符串长度的2倍,即((2*p[i]-1)-1)/2 = p[i]-1,得证。
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文子串
- 最长回文串模版
- 最长回文子串
- 最长回文子串
- bjfu---1188 A Simple Math Problem
- 10010 - Where's Waldorf?
- URL 加载到页面的完整过程
- linux(三)(shell 相关)
- hdu---2154跳舞毯
- 最长回文串
- Android应用程序内换肤解决方案(二)之测试Demo
- hdu---2529Shot
- hdu---2058The sum problem
- hdu---1719Friend
- 数据结构之一:栈的实现
- hdu---1577WisKey的眼神
- hdu---1591Encoded Love-letter
- Maximum Subarray