HDU - 3068 + Manacher最大回文子串

给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 
回文就是正反读都是一样的字符串,如aba, abba等
Input输入有多组case,不超过120组,每组输入为一行小写英文字符a,b,c...y,z组成的字符串S 
两组case之间由空行隔开(该空行不用处理) 
字符串长度len <= 110000Output每一行一个整数x,对应一组case,表示该组case的字符串中所包含的最长回文长度. 
Sample Input
aaaa

abab
Sample Output
4

3




import java.util.*;
public class Main {
	static int maxn = 110000 + 2000;
	static char[] new_s = new char[maxn*2];
	static int[] p = new int[maxn*2];//p[i],表示以i为中心的最长回文的半径
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		while (in.hasNext()) {
			Arrays.fill(new_s, '#');
			Arrays.fill(p, 0);
			String s = in.next();
			Manacher(s);
		}
	}

	private static void Manacher(String s) {
		int len = init(s);
		int max_len = 0;
		int id = 0;
		for (int i = 1; i < len; i++) {
			if (p[id] + id > i) {
				p[i] = Math.min(p[id*2 - i], p[id] + id - i);//id*2 - i 是i关于id的对称点
			}
			else {
				p[i] = 1;
			}
			while (new_s[i - p[i]] == new_s[i + p[i]]) {//一直更新p[i],直到以i为中心的半径不再增加
				p[i]++;
			}
			if (p[id] + id < p[i] + i) id = i;//更新id
			max_len = Math.max(max_len, p[i] - 1);//更新最大长度
		}
		System.out.println(max_len);
	}

	private static int init(String s) {
		int len = s.length();
		new_s[0] = '$';
		new_s[1] = '#';
		int j = 2;
		for (int i = 0; i < len; i++) {
			new_s[j++] = s.charAt(i);
			new_s[j++] = '#';
		}
//		new_s[j] = '\0';
		return j;
	}
}

C++版:

#include <cstdio>
#include <iostream>
#include <vector>
#include <cmath>
#include <map>
#include <set>
#include <cstring>
using namespace std;
const int maxn = 110000 + 10000;
char s[maxn], new_s[maxn*2];
int p[maxn*2];
int init() {
    memset(p, 0, sizeof(p));
    int len = strlen(s);
    new_s[0] = '$';
    new_s[1] = '#';
    int j = 2;
    for (int i = 0; i < len; i++) {
        new_s[j++] = s[i];
        new_s[j++] = '#';
    }
    new_s[j] = '\0';
    return j;
}
int max(int a, int b) {
    if (a > b) return a;
    else return b;
}
int min(int a, int b) {
    if (a < b) return a;
    else return b;
}
int main() {
    while (~scanf("%s", s)) {

        int len = init();

        int max_len = 0;
        int id = 0;
        int mx = 0;
        for (int i = 1; i < len; i++) {
            if (i < mx) {
                p[i] = min(p[2*id - i], mx - i);
            }
            else {
                p[i] = 1;
            }
            while (new_s[i - p[i]] == new_s[i + p[i]]) { p[i]++; }
            if (mx < p[i] + i) { id = i; mx = i + p[i]; }
            max_len = max(max_len, p[i] - 1);
        }
        printf("%d\n", max_len);
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/qq_34649947/article/details/80391735