アルゴリズム学習——文字列の中で最も長い回文のサブ列を探す
20173 ワード
文章は公衆番号「インターネット捜査」から転載された.
実行結果:原字列:abcdcef最長回文列:cdc原字列:adaelle最長回文列:elele原字列:cabadabae最長回文列:abadaba原字列:aaabcdefgfedcbaa最長回文列:aaabcdefgfedcbaa原字列:aabaa最長回文列:aaaaaaaaaaa
/**
* @author xiaoshi on 2018/9/24.
* Happy Mid-Autumn Festival
*/
public class PlalindromeString {
// ,
@Deprecated
private boolean isPlalindrome(String s) {
int len = s.length();
for(int i = 0; i < len / 2; i++) {
if(s.charAt(i) != s.charAt(len - 1 - i)) {
return false;
}
}
return true;
}
// , #
private String preHandleString(String s) {
StringBuffer sb = new StringBuffer();
int len = s.length();
sb.append('#');
for(int i = 0; i < len; i++) {
sb.append(s.charAt(i));
sb.append('#');
}
return sb.toString();
}
//
public String findLongestPlalindromeString(String s) {
//
String str = preHandleString(s);
//
int len = str.length();
//
int rightSide = 0;
//
int rightSideCenter = 0;
// ( )
int[] halfLenArr = new int[len];
//
int center = 0;
//
int longestHalf = 0;
for(int i = 0; i < len; i++) {
//
boolean needCalc = true;
//
if(rightSide > i) {
// rightSideCenter
int leftCenter = 2 * rightSideCenter - i;
//
halfLenArr[i] = halfLenArr[leftCenter];
// ,
if(i + halfLenArr[i] > rightSide) {
halfLenArr[i] = rightSide - i;
}
// ,
if(i + halfLenArr[leftCenter] < rightSide) {
//
needCalc = false;
}
}
//
if(needCalc) {
while(i - 1 - halfLenArr[i] >= 0 && i + 1 + halfLenArr[i] < len) {
if(str.charAt(i + 1 + halfLenArr[i]) == str.charAt(i - 1 - halfLenArr[i])) {
halfLenArr[i]++;
} else {
break;
}
}
//
rightSide = i + halfLenArr[i];
rightSideCenter = i;
//
if(halfLenArr[i] > longestHalf) {
center = i;
longestHalf = halfLenArr[i];
}
}
}
// #
StringBuffer sb = new StringBuffer();
for(int i = center - longestHalf + 1; i <= center + longestHalf; i += 2) {
sb.append(str.charAt(i));
}
return sb.toString();
}
}
/**
* @author lixin on 2018/9/24.
*/
public class Main {
public static void main(String[] args) {
PlalindromeString ps = new PlalindromeString();
String[] testStrArr = new String[] {
"abcdcef",
"adaelele",
"cabadabae",
"aaaabcdefgfedcbaa",
"aaba",
"aaaaaaaaa"
};
for(String str : testStrArr) {
System.out.println(String.format(" : %s", str));
System.out.println(String.format(" : %s", ps.findLongestPlalindromeString(str)));
System.out.println();
}
}
}
実行結果:原字列:abcdcef最長回文列:cdc原字列:adaelle最長回文列:elele原字列:cabadabae最長回文列:abadaba原字列:aaabcdefgfedcbaa最長回文列:aaabcdefgfedcbaa原字列:aabaa最長回文列:aaaaaaaaaaa