给定一个仅包含小写字母的字符串,求它的最长回文子串的长度。
所谓回文串,指左右对称的字符串。
所谓子串,指一个字符串删掉其部分前缀和后缀(也可以不删)的字符串
数据范围:字符串长度
进阶:时间复杂度:,空间复杂度:
import java.util.Scanner; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; // 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String line = br.readLine(); int maxLen = 0; for (int i = 0; i < line.length(); i++) { for (int j = i + 1; j <= line.length(); j++) { // 回文字符串 反转后与其自身相等 String sub = line.substring(i, j); StringBuilder sb = new StringBuilder(sub); if (sub.equals(sb.reverse().toString()) && sub.length() > maxLen) { maxLen = sub.length(); } } } System.out.println(maxLen); } }
import java.util.*; // 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); // 使用双指针法,从中心点到两边扩散,注意有两种星形式的回文子串 String str = in.nextLine(); // 定义左右指针 int l; int r; // 定义集合接收回文字符的长度 ArrayList<Integer> list = new ArrayList<>(); for (int i = 0; i < str.length() - 2; i++) { // ABBA型 int len1 = 0; if (str.charAt(i) == str.charAt(i + 1)) { // 两边发散继续寻找 l = i; r = i + 1; do { len1 += 2; l--; r++; } while (r < str.length() && str.charAt(l) == str.charAt(r)); } // ABA型 不是加2 初始值是1 int len2 = 1; if (str.charAt(i) == str.charAt(i + 2)) { // 两边发散继续寻找 l = i; r = i + 2; do { len2 += 2; l--; r++; //防止数组越界异常前置判断 } while (l >= 0 && r < str.length() && str.charAt(l) == str.charAt(r)); } list.add(Math.max(len1, len2)); } System.out.println(Collections.max(list)); } }
import java.util.Scanner; // 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); String a = in.nextLine(); int max = 0; for (int i = 0; i < a.length(); i++) { for (int j = i+1; j <= a.length(); j++) { String sub = a.substring(i,j); if (isPalindrome(sub) && sub.length() > max){ max = sub.length(); } } } System.out.println(max); } private static boolean isPalindrome(String str){ StringBuilder sub = new StringBuilder(str).reverse(); if (str.equals(sub.toString())){ return true; } return false; } }
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); String line = in.nextLine(); int num = 1; // 默认回文最小长度为1(单个字符) for (int i = 0; i < line.length(); i++) { // 回文长度为偶数 int k = Math.min(i + 1, line.length() - i - 1); int idx = 0; while (k > idx) { if (line.charAt(i - idx) != line.charAt(i + 1 + idx)) { break; } idx++; } num = Math.max(num, 2 * idx); // 回文长度为奇数 k = Math.min(i, line.length() - i - 1); idx = 0; while (k > idx) { if (line.charAt(i - 1 - idx) != line.charAt(i + 1 + idx)) { break; } idx++; } num = Math.max(num, 2 * idx + 1); } System.out.println(num); } }
import java.util.*; // 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main { public static int[] p1=new int[400]; public static int[] p2=new int[400]; public static int[] p3=new int[400]; public static int[] dp=new int[400]; public static boolean check(int x,int y){ int a=p2[y]-p2[x-1]*p1[y-x+1]; int b=p3[x]-p3[y+1]*p1[y-x+1]; return a==b; } public static void main(String[] args) { Scanner in = new Scanner(System.in); // 注意 hasNext 和 hasNextLine 的区别 while (in.hasNext()) { // 注意 while 处理多个 case Arrays.fill(p2,0); Arrays.fill(p3,0); Arrays.fill(dp,0); String s=in.next(); int n=s.length(),ans=0; p1[0]=1; for(int i=1;i<=n;i++){ dp[i]=1; p1[i]=p1[i-1]*27; p2[i]=p2[i-1]*27+(s.charAt(i-1)-'a'); p3[n-i+1]=p3[n-i+2]*27+(s.charAt(n-i)-'a'); } for(int i=1;i<=n;i++){ if(i-dp[i-1]>0&&check(i-dp[i-1],i)) dp[i]=Math.max(dp[i-1]+1,dp[i]); if(i-1-dp[i-1]>0&&check(i-1-dp[i-1],i)) dp[i]=Math.max(dp[i-1]+2,dp[i]); ans=Math.max(ans,dp[i]); } System.out.println(ans); } } }
/** * ☆☆☆☆☆ * 最长回文子串 * 中心扩展 + 动态规划 + Manacher */ private static void longestPalindrome2() { Scanner in = new Scanner(System.in); while (in.hasNext()) { String s = in.nextLine(); // 字符间隔及两边插入#,方便统一中心扩展方式的两种情况:中心在元素上和中心在元素间 StringBuilder sb = new StringBuilder("#"); for (int i = 0; i < s.length(); i++) { sb.append(s.charAt(i)).append("#"); } // 数组用于存插入#后,当前元素为中心的最大回文半径(自身算1) // 最终的最大回文长度是该半径-1(该半径多出来的#,比另一边的原字符多一) int[] arr = new int[sb.length()]; // 已知的所有回文串的最右边界+1 int maxPos = 0; // 边界最右的回文串的中心 int index = 0; for (int i = 0; i < sb.length(); i++) { if (i < maxPos) { // 此处是关键,i相对index的对称位置2*index-i,直接参与计算,避免重复计算 arr[i] = Math.min(arr[2 * index - i], maxPos - i); } else { arr[i] = 1; } // 在已有基础上继续扩展判断,越界判断,以及两边字符判断 while (i - arr[i] >= 0 && i + arr[i] < sb.length() && sb.charAt(i - arr[i]) == sb.charAt(i + arr[i])) { arr[i]++; } // 更新maxpos和index if (i + arr[i] > maxPos) { maxPos = i + arr[i]; index = i; } } int max = 0; for (int i = 0; i < sb.length(); i++) { max = Math.max(max, arr[i]); } // 最长回文串的长度 System.out.println(max - 1); // 最长回文串 for (int i = 0; i < sb.length(); i++) { if (max == arr[i]) { String result = sb.substring(i - arr[i] + 1, i + arr[i]).replace("#", ""); System.out.println(result); break; } } } }
import java.util.Scanner; // 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); // 注意 hasNext 和 hasNextLine 的区别 while (in.hasNext()) { // 注意 while 处理多个 case String str = in.nextLine(); // dp[i][j]数组, 标记下标i-j是否为回文串, // 1. 单个字符肯定是回文串, dp[i][i] == true // 2. 如果i~j是回文子串,那么i+1~j-1肯定也是回文子串 String subStr = getMaxLongStr(str); System.out.println(subStr.length()); } } private static String getMaxLongStr(String str) { int begin = 0; int maxLen = 1; int len = str.length(); char[] arr = str.toCharArray(); // 定义dp数组 // 单个字符都是回文 boolean[][] dp = new boolean[len][len]; for (int i = 0; i < len; i++) { dp[i][i] = true; } // dp[i][j] 参考的是 dp[i+1][j-1] // 边界条件: (j-1) - (i+1) + 1 < 2,则不需要参考 // 整理: j - i < 3 for (int j = 1; j < len; j++) { for (int i = 0; i < j; i ++) { if (arr[i] != arr[j]) { dp[i][j] = false; } else { if (j - i < 3) { dp[i][j] = true; } else { dp[i][j] = dp[i+1][j-1]; } } // 更新最大子串 if (dp[i][j] && j - i + 1 > maxLen) { begin = i; maxLen = j - i + 1; } } } return str.substring(begin, begin+maxLen); } }
import java.util.Scanner; // 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); String s1 = in.nextLine(); in.close(); int size = s1.length(); int res = 1; for (int k = 0; k < size; k++) { res = Math.max(res, centreExtend(s1, k, k, size)); } for (int k = 0; k < size-1; k++) { if (s1.charAt(k) == s1.charAt(k+1)) { res = Math.max(res, centreExtend(s1, k, k+1, size)); } } System.out.println(res); } private static int centreExtend(String s1, int i, int j, int size) { while (i-1 >= 0 && j+1 < size && s1.charAt(i-1) == s1.charAt(j+1)) { i--; j++; } return j - i + 1; } }
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); String str = in.nextLine(); char[] ch = str.toCharArray(); int lengthMax = 0; for (int i = 0; i < str.length() - 1; i++) { // 找到一个长度为2的回文子串 if (ch[i] == ch[i + 1]) { int temp = 1; // 该次遍历最长回文串 String strMax; // 同时向该回文子串两边向外递增直至不对称 while ((i - temp) >= 0 && (i + 1 + temp) < ch.length) { if (ch[i - temp] == ch[i + 1 + temp]) { temp++; } else { break; } } // 截取temp-1时的情况,此时即当前i时最大回文字符串 strMax = str.substring(i - temp + 1, i + 1 + temp); if (lengthMax < strMax.length()) { lengthMax = strMax.length(); } } // 找到一个长度为3的回文子串 if (i - 1 >= 0 && ch[i - 1] == ch[i + 1]) { int temp = 1; // 该次遍历最长回文串 String strMax; // 同时向该回文子串两边向外递增直至不对称 while ((i - 1 - temp) >= 0 && (i + 1 + temp) < ch.length) { if (ch[i - 1 - temp] == ch[i + 1 + temp]) { temp++; } else { // 外扩后左右字符不同时 break; } } // 截取temp-1时的情况,此时即当前i时最大回文字符串 strMax = str.substring(i - 1 - temp + 1, i + 1 + temp); // 找所有最大情况 if (lengthMax < strMax.length()) { lengthMax = strMax.length(); } } } System.out.println(lengthMax); } }
求出所有的子字符串,再利用子字符串比较,简单易懂
import java.io.BufferedReader; import java.io.IOException; import java.util.*; import java.util.ArrayList; public class Main { public static void main(String[] args) throws IOException { Scanner scan = new Scanner(System.in); String str = scan.next(); if(str.length()==0){ System.out.print(0); return; } StringBuilder stb = new StringBuilder(str); String temp = stb.reverse().toString(); int max = 1; int len = str.length(); ArrayList <String> arr = new ArrayList<String>(); for(int i=0;i<len-1;i++){ for(int j=i;j<=len;j++){ arr.add(str.substring(i,j)); } } for(int i=0;i<arr.size();i++){ String ss =arr.get(i); if(ss.equals(new StringBuilder(ss).reverse().toString())){ if(max< ss.length()) max = ss.length(); } } System.out.print(max); } }
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String s = sc.nextLine(); int n = s.length(); int[][] dp = new int[n][n]; int res = 1; for(int i = n - 1;i >= 0;i--){ dp[i][i] = 1; for(int j = i + 1;j < n;j++){ if(s.charAt(i) == s.charAt(j)){ if(j - i < 3){ dp[i][j] = j - i + 1; }else{ dp[i][j] = dp[i + 1][j - 1] > 0 ? j - i + 1 : 0; } if(dp[i][j] > 0 && j - i + 1 > res) res = j - i + 1; } } } System.out.println(res); } }
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.*; public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String str; while((str=br.readLine())!=null){ int max=0; for(int i=0;i<str.length()-1;i++){ for(int j=str.length()-1;j>i;j--){ if(max>j-i+1){ break; } String nstr=str.substring(i,j+1); boolean flag=true; for(int a=0;a<=nstr.length()/2;a++){ if(nstr.charAt(a)!=nstr.charAt(nstr.length()-1-a)){ flag=false; break; } } if(flag&&nstr.length()>max){ max=nstr.length(); } } if(max>str.length()-i){ break; } } System.out.println(max); } } }