首页 > 代码库 > Leetcode5--->最长回文子串
Leetcode5--->最长回文子串
题目:给定一个字符串s,找出s中的最长回文子串;
暴力法,DP法, 中心扩展法,manacher算法
解法一:暴力法
遍历字符串S的每一个子串,去判断这个子串是不是回文,是回文的话看看长度是不是比最大的长度maxlength大。遍历每一个子串的方法要O(n^2),判断每一个子串是不是回文的时间复杂度是O(n),所以暴利方法的总时间复杂度是O(n^3)。
1 public static String findLongestPalindrome(String s){ 2 int len = s.length(); // 字符串长度 3 int maxlength = 0; // 最长回文字符串长度 4 int start = 0; // 回文开始的地方 5 for(int i = 0; i < len; i++){ 6 for(int j = i + 1; j < len; j++){ 7 int index1 = 0; 8 int index2 = 0; 9 // 对每个子串都从两边开始向中间遍历10 for(index1 = i, index2 = j; index1 < index2; index1 ++, index2--){11 if(s.charAt(index1) != s.charAt(index2))12 break;13 }14 // 若index1=index2,表示串是类似于abcba这种类型;若大于,则是abccba这种类型15 if(index1 >= index2 && j - i > maxlength){16 maxlength = j - i + 1;17 start = i;18 }19 }20 21 }22 if(maxlength > 0)23 return s.substring(start, start + maxlength);24 return null;25 26 }
解法二: 动态规划
回文字符串的子串也是回文,比如P[i,j](表示以i开始以j结束的子串)是回文字符串,那么P[i+1,j-1]也是回文字符串。这样最长回文子串就能分解成一系列子问题了。这样需要额外的空间O(N^2),算法复杂度也是O(N^2)。
首先定义状态方程和转移方程:
P[i,j]=false:表示子串[i,j]不是回文串。P[i,j]=true:表示子串[i,j]是回文串。
P[i,i]=true:当且仅当P[i+1,j-1] = true && (s[i]==s[j])
否则p[i,j] =false;
1 public static String findLongestPalindrome1(String s){ 2 int len = s.length(); 3 int start = 0; 4 int maxlength = 0; 5 boolean p[][] = new boolean[s.length()][s.length()]; 6 // 子串长度为1和为2的初始化 7 for(int i = 0; i < len; i++){ 8 p[i][i] = true; 9 if(i < len - 1 && s.charAt(i) == s.charAt(i + 1)){10 p[i][i + 1] = true;11 start = i;12 maxlength = 2;13 }14 }15 // 使用上述结果可以dp出子串长度为3~len -1的子串16 for(int strlen = 3; strlen < len; strlen ++){17 for(int i = 0; i <=len - strlen; i++){18 int j = i + strlen - 1; // 子串结束的位置19 if(p[i + 1][j - 1] && s.charAt(i) == s.charAt(j)){20 p[i][j] = true;21 maxlength = strlen;22 start = i;23 }24 }25 }26 if(maxlength > 0)27 return s.substring(start, start + maxlength);28 return null;29 }
解法三:中心扩展法
中心扩展就是把给定的字符串的每一个字母当做中心,向两边扩展,这样来找最长的子回文串。算法复杂度为O(N^2)。
但是要考虑两种情况:
1、像aba,这样长度为奇数。
2、想abba,这样长度为偶数。
1 public static String findLongestPalindrome2(String s){ 2 int len = s.length(); 3 int maxlength = 0; 4 int start = 0; 5 // 类似于aba这种情况,以i为中心向两边扩展 6 for(int i = 0; i < len; i++){ 7 int j = i - 1; 8 int k = i + 1; 9 while(j >= 0 && k < len && s.charAt(j) == s.charAt(k)){10 if(k - j + 1 > maxlength){11 maxlength = k - j + 1;12 start = j;13 }14 j --;15 k ++;16 }17 }18 // 类似于abba这种情况,以i,i+1为中心向两边扩展19 for(int i = 0; i < len; i++){20 int j = i;21 int k = i + 1;22 while(j >= 0 && k <len && s.charAt(j) == s.charAt(k)){23 if(k - j + 1 > maxlength){24 maxlength = k - j + 1;25 start = j;26 }27 j --;28 k ++;29 }30 }31 if(maxlength > 0)32 return s.substring(start, start + maxlength);33 return null;34 }
解法四:Manacher算法
Manacher法只能解决例如aba这样长度为奇数的回文串,对于abba这样的不能解决,于是就在里面添加特殊字符。我是添加了“#”,使abba变为a#b#b#a。这个算法就是利用已有回文串的对称性来计算的,具体算法复杂度为O(N)
1 public static String findLongestPalindrome3(String s) { 2 if(s == null || s.length() < 1) 3 return ""; 4 String str = dealWithS(s); // 处理一下s,即将给字符串s的中间加上特殊字符,这样无论对于奇数字符还是偶数字符可以做同样的处理 5 int[] res = new int[str.length()]; 6 int R = 0; // 当前所能扩展的半径 7 int C = 0; // C位置的半径为R 8 int maxC= 0; // 最长的半径的位置 9 res[0] = 0;10 for(int i = 1; i < str.length(); i++)11 {12 int j = 2 * C - i; // i点的对称点13 if(j >= 0 && res[j] < R - i) // 对称点存在且对称点的回文半径在C的回文中14 {15 res[i] = res[j];16 }17 else // 否则,需要根据i点一点一点的计算18 {19 int k = 1;20 while(R + k < str.length() && 2 * i - R - k >= 0)21 {22 if(str.charAt(R + k) == str.charAt(2 * i - R - k))23 k ++;24 else25 break;26 }27 res[i] = R -i + k - 1;28 if(res[i] + i > R)29 {30 R = res[i] + i;31 C = i;32 }33 }34 35 maxC = res[maxC] > res[i] ? maxC : i; // maxC保存的是回文半径最大的那个点的位置36 }37 String subStr = str.substring(maxC - res[maxC], maxC + res[maxC] + 1);38 StringBuffer sb = new StringBuffer();39 for(int i = 0; i < subStr.length(); i++)40 {41 if(subStr.charAt(i) != ‘#‘)42 sb.append(subStr.charAt(i));43 }44 return sb.toString();45 }46 public static String dealWithS(String s) // 将原字符串进行处理47 {48 StringBuffer sb = new StringBuffer();49 sb.append("#");50 for(int i = 0; i < s.length (); i++)51 {52 sb.append(s.charAt(i));53 sb.append("#");54 }55 return sb.toString();56 }
Leetcode5--->最长回文子串
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。