1 /**
2 * 最长回文子字符串
3 *
4 * @author 林夕
5 */
6 public class Solution {
7
8 public static void main(String[] args) {
9 // String s =
10 // "rgczcpratwyqxaszbuwwcadruayhasynuxnakpmsyhxzlnxmdtsqqlmwnbxvmgvllafrpmlfuqpbhjddmhmbcgmlyeypkfpreddyencsdmgxysctpubvgeedhurvizgqxclhpfrvxggrowaynrtuwvvvwnqlowdihtrdzjffrgoeqivnprdnpvfjuhycpfydjcpfcnkpyujljiesmuxhtizzvwhvpqylvcirwqsmpptyhcqybstsfgjadicwzycswwmpluvzqdvnhkcofptqrzgjqtbvbdxylrylinspncrkxclykccbwridpqckstxdjawvziucrswpsfmisqiozworibeycuarcidbljslwbalcemgymnsxfziattdylrulwrybzztoxhevsdnvvljfzzrgcmagshucoalfiuapgzpqgjjgqsmcvtdsvehewrvtkeqwgmatqdpwlayjcxcavjmgpdyklrjcqvxjqbjucfubgmgpkfdxznkhcejscymuildfnuxwmuklntnyycdcscioimenaeohgpbcpogyifcsatfxeslstkjclauqmywacizyapxlgtcchlxkvygzeucwalhvhbwkvbceqajstxzzppcxoanhyfkgwaelsfdeeviqogjpresnoacegfeejyychabkhszcokdxpaqrprwfdahjqkfptwpeykgumyemgkccynxuvbdpjlrbgqtcqulxodurugofuwzudnhgxdrbbxtrvdnlodyhsifvyspejenpdckevzqrexplpcqtwtxlimfrsjumiygqeemhihcxyngsemcolrnlyhqlbqbcestadoxtrdvcgucntjnfavylip";
11 String s = "babcbabcbaccba";
12 // System.out.println(isPalindrome(s));
13 long sTime = System.currentTimeMillis();
14 String t = method4(s);
15 // String t = longestPalindrome(s);
16 long eTime = System.currentTimeMillis();
17 System.out.println(t);
18 System.out.println("执行时间为" + (eTime - sTime) + "ms"); // 执行时间为75ms
19 }
20
21 /**
22 * 非常规情况:多个最长回文子字符串长度相等 ? 最笨的办法 时间复杂度为O(n^3)
23 * 本身有n^2个字符串,检查一个子串是否为回文串又需要O(n)的时间
24 */
25 public static String longestPalindrome(String s) {
26 int l = s.length();
27 String res = null;
28 int max = Integer.MIN_VALUE;
29 for (int i = 0; i < l; i++) {
30 for (int j = i; j < l; j++) {
31 String temp = s.substring(i, j + 1);
32 if (isPalindrome(temp)) {
33 if (temp.length() > max) {
34 max = temp.length();
35 res = temp;
36 }
37 }
38 }
39 }
40 return res;
41 }
42
43 /**
44 * 判断是否为回文字符串
45 */
46 public static boolean isPalindrome(String s) {
47 int l = s.length();
48 int temp = (int) Math.floor((double) l / 2); // floor为向下取整
49 for (int i = 0; i < temp; i++) {
50 if (s.charAt(i) != s.charAt(l - 1 - i)) {
51 return false;
52 }
53 }
54 return true;
55 }
56
57 /**
58 * 时间复杂度:O(n^2) 空间复杂度:O(n^2)
59 * 算法理解:http://articles.leetcode.com/longest-palindromic-substring-part-i
60 */
61 public static String method2(String s) {
62 int n = s.length();
63 int longestBegin = 0;
64 int maxLen = 1;
65 boolean[][] table = new boolean[1000][1000];
66 for (int i = 0; i < 1000; i++) {
67 for (int j = 0; j < 1000; j++) {
68 table[i][j] = false;
69 }
70 }
71
72 for (int i = 0; i < 1000; i++) {
73 table[i][i] = true;
74 }
75
76 for (int i = 0; i < n - 1; i++) {
77 if (s.charAt(i) == s.charAt(i + 1)) {
78 table[i][i + 1] = true;
79 longestBegin = i;
80 maxLen = 2;
81 }
82 }
83
84 for (int len = 3; len <= n; len++) {
85 for (int i = 0; i < n - len + 1; i++) {
86 int j = i + len - 1;
87 if (s.charAt(i) == s.charAt(j) && table[i + 1][j - 1]) {
88 table[i][j] = true;
89 longestBegin = i;
90 maxLen = len;
91 }
92 }
93 }
94 return s.substring(longestBegin, longestBegin + maxLen);
95 }
96
97 /**
98 * 时间复杂度:O(n^2) 有2N-1个Center 空间复杂度:O(1)
99 */
100 public static String method3(String s) {
101 int n = s.length();
102 if (n == 0) {
103 return "";
104 }
105 String longest = s.substring(0, 1);
106 for (int i = 0; i < n - 1; i++) {
107 String p1 = expandAroundCenter(s, i, i);
108 if (p1.length() > longest.length()) {
109 longest = p1;
110 }
111
112 String p2 = expandAroundCenter(s, i, i + 1);
113 if (p2.length() > longest.length()) {
114 longest = p2;
115 }
116 }
117 return longest;
118 }
119
120 /**
121 * 辅助函数 以c1,c2为中心扩展字符串
122 *
123 * @param s
124 * @param c1
125 * @param c2
126 * @return
127 */
128 public static String expandAroundCenter(String s, int c1, int c2) {
129 int l = c1, r = c2;
130 int n = s.length();
131 while (l >= 0 && r <= n - 1 && s.charAt(l) == s.charAt(r)) {
132 l--;
133 r++;
134 }
135 return s.substring(l + 1, r);
136 }
137
138 /**
139 * 时间复杂度:O(n) 空间复杂度:O(n) Manacher’s algorithm
140 * http://articles.leetcode.com/longest-palindromic-substring-part-ii
141 */
142 public static String method4(String s) {
143 String T = preProcess(s);
144 int n = T.length();
145 int[] P = new int[n];
146 int C = 0, R = 0;
147 for (int i = 1; i < n - 1; i++) {
148 int i_mirror = 2 * C - i;
149 P[i] = (R > i) ? Math.min(R - i, P[i_mirror]) : 0;
150
151 while (T.charAt(i + 1 + P[i]) == T.charAt(i - 1 - P[i]))
152 P[i]++;
153
154 // If palindrome centered at i expand past R,
155 // adjust center based on expanded palindrome.
156 if (i + P[i] > R) {
157 C = i;
158 R = i + P[i];
159 }
160 }
161 // Find the maximum element in P.
162 int maxLen = 0;
163 int centerIndex = 0;
164 for (int i = 0; i < n - 1; i++) {
165 if (P[i] > maxLen) {
166 maxLen = P[i];
167 centerIndex = i;
168 }
169 }
170
171 return s.substring((centerIndex - 1 - maxLen) / 2, (centerIndex - 1 + maxLen) / 2);
172 }
173
174 private static String preProcess(String s) {
175 int n = s.length();
176 if (n == 0) {
177 return "^$";
178 }
179 String ret = "^";
180
181 for (int i = 0; i < n; i++)
182 ret += "#" + s.substring(i, i + 1);
183
184 ret += "#$";
185 return ret;
186
187 }
188
189 }