java实现第六届蓝桥杯切开字符串

切开字符串

Pear有一个字符串,不过他希望把它切成两段。
这是一个长度为N(<=10^5)的字符串。
Pear希望选择一个位置,把字符串不重复不遗漏地切成两段,长度分别是t和N-t(这两段都必须非空)。

Pear用如下方式评估切割的方案:
定义“正回文子串”为:长度为奇数的回文子串。
设切成的两段字符串中,前一段中有A个不相同的正回文子串,后一段中有B个不相同的非正回文子串,则该方案的得分为A*B。

注意,后一段中的B表示的是:“…非正回文…”,而不是: “…正回文…”。
那么所有的切割方案中,A*B的最大值是多少呢?

【输入数据】
输入第一行一个正整数N(<=10^5)
接下来一行一个字符串,长度为N。该字符串仅包含小写英文字母。
【输出数据】
一行一个正整数,表示所求的A*B的最大值。
【样例输入】
10
bbaaabcaba
【样例输出】
38
【数据范围】
对于20%的数据,N<=100
对于40%的数据,N<=1000
对于100%的数据,N<=10^5

资源约定:
峰值内存消耗(含虚拟机) < 512M
CPU消耗 < 2000ms

请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。

以下代码对于N大于10000可能会超时,代码仅供参考。
import java.util.HashSet;
import java.util.Scanner;

public class Main {
    public static String A, S;
    
    public int Manacher(String M, String N) {
        int count = 0;  //统计字符串M中不同正回文串个数
        int[] P = new int[M.length()];
        int mx = 0, id = 0;
        for(int i = 1;i < M.length();i++) {
            if(mx > i)
                P[i] = Math.min(P[2 * id - i], mx - i);
            else
                P[i] = 1;
            while(i+P[i] < M.length() && i-P[i] >= 0 && 
                    M.charAt(i+P[i]) == M.charAt(i-P[i]))
                P[i]++;
            if(P[i] + i > mx) {
                mx = i + P[i];
                id = i;
            }
        }
        HashSet set = new HashSet();
        for(int i = 2;i < P.length;i = i + 2) {
            int len = P[i] - 1;
            int j = i / 2 - 1;  //回文串中心字符在字符串N中的位置
            if(len == 0) {
                String s = N.substring(j, j + 1);
                if(!set.contains(s)) {
                    set.add(s);
                    count++;
                }
            } else if(len % 2 == 1){
                for(int k = 0;k <= len / 2;k++) {
                    String s = N.substring(j - k, j + k + 1);
                    if(!set.contains(s)) {
                        set.add(s);
                        count++;
                    }
                }
            }
        }
        return count;
    }
    
    public int getAllChildern(String M) {
        int count = 0;  //统计字符串M所有不同子串个数
        HashSet set = new HashSet();
        for(int i = 0, len = 1;i < M.length();i++, len++) {
            for(int j = 0;j <= M.length() - len;j++) {
                String s = M.substring(j, j + len);
                if(!set.contains(s)) {
                    set.add(s);
                    count++;
                }
            }
        }
        return count;
    }
    
    public void getResult() {
        int max = -1;
        for(int i = 1;i < A.length() - 1;i++) {
            String s1 = S.substring(0, i * 2 + 1);
            String s2 = "$" + S.substring(i * 2 + 1);
            String s3 = A.substring(0, i);
            String s4 = A.substring(i);
            int a = Manacher(s1, s3);
            int b = getAllChildern(s4) - Manacher(s2, s4);
            max = Math.max(max, a * b);
        }
        System.out.println(max);
    }
    
    public static void main(String[] args) {
        Main test = new Main();
        Scanner in = new Scanner(System.in);
        A = in.next();
        StringBuilder s1 = new StringBuilder("$#");
        for(int i = 0;i < A.length();i++) {
            s1.append(A.charAt(i));
            s1.append("#");
        }
        S = s1.toString();
        test.getResult();
    }
}

PS:纯暴力

package 第七次模拟;

import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

public class Demo8切开字符串 {
	static int n;
	static String str = new String();
	static int max = 0;
	static int A, B, C;
    public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		n = in.nextInt();
		str = in.next();
		for (int t = 1; t < n-1; t++) {
			A = panduan(str.substring(0, t));
			B = quan(str.substring(t, n)) - panduan(str.substring(t, n));
			if (max < A*B) {
				max = A*B;
			}
		}
		System.out.println(max);
	}
    /**
     * B的要求是找出 不相同的非正回文子串 这里采用曲线救国的方案,求出B的 全部不相同子串 的个数,减去B中 不相同的正回文子串 的个数
     * 
     * */
	private static int quan(String sub) {
		// TODO Auto-generated method stub
		Set set = new HashSet();
		for (int i = 1; i <= sub.length(); i++) {
			for (int start = 0; start <= sub.length()-i; start++) {
				String s = sub.substring(start, start+i);
				set.add(s);
			}
		}
		return set.size();
	}
	/**
	 * 对于一个字符串,查找其中包含的正回文串个数
	 * */
	private static int panduan(String sub) {
		// TODO Auto-generated method stub
		Set set = new HashSet();
		set.clear();
		for (int i = 1; i <= sub.length(); i+=2) {
			for (int start = 0; start <= sub.length()-i; start++) {
				String s = sub.substring(start, start+i);
				if (huiwen(s) == true) {
					set.add(s);
				}
			}
		}
		return set.size();
	}
	/**
	 * 判断回文
	 * */
	private static boolean huiwen(String s) {
		// TODO Auto-generated method stub
		for (int i = 0; i < s.length()/2; i++) {
			if (s.charAt(i) == s.charAt(s.length()-1-i)) {
				continue;
			} else {
				return false;
			}
		}
		return true;
	}


}

你可能感兴趣的:(算法练习题)