美文网首页
对称子字符串

对称子字符串

作者: asdfgjsrgdf | 来源:发表于2019-11-19 18:46 被阅读0次

    问题描述

           Given a string ‘str’ of digits, find length of the longest substring of ‘str’, such that the length of the substring is 2k digits and sum of left k digits is equal to the sum of right k digits.

    输入

           输入第一行是测试用例的个数,后面每一行表示一个数字组成的字符串,例如:"123123"

    输出

           输出找到的满足要求的最长子串的长度。例如,给定的例子长度应该是 6。每行对应一个用例的结果。

    示例输入

    1
    1538023

    示例输出

    4

    1.递归解法

           (1)若输入的数字字符串长度length为0或1,则结果为0
           (2)若输入的数字字符串长度length为偶数:
                  a. 若前length/2位之和等于后length/2之和===>返回结果length
                  b. 若前length/2位之和不等于后length/2之和:===>寻找长度为length-2的子字符串:



           (3)若输入的数字字符串长度length为奇数===>寻找长度为length-1的子字符串:



           代码:
    import java.util.Scanner;
    
    public class SymSubstr {
        public static void main(String args[]){
            Scanner sc = new Scanner(System.in);
            int casesnum = sc.nextInt();
            sc.nextLine();
            while(casesnum>0){
                String temp = sc.nextLine();
                int[] input = new int[temp.length()];
                for(int i=0;i<input.length;i++){
                    input[i] = Integer.parseInt(temp.charAt(i)+"");
                }
                int result = find(input);
                System.out.println(result);
                casesnum --;
            }
        }
    
        public static int find(int[] input){
            if(input.length==0)
                return 0;
            if(input.length%2 == 0){
                int sum1 = 0;
                int sum2 = 0;
                for(int i=0;i<input.length/2;i++){
                    sum1 += input[i];
                }
                for(int i=input.length/2;i<input.length;i++){
                    sum2 += input[i];
                }
                if(sum1 == sum2)
                    return input.length;
                else{
                    int[] new1 = new int[input.length-2];
                    int[] new2 = new int[input.length-2];
                    int[] new3 = new int[input.length-2];
                    for(int i=0;i<input.length-2;i++){
                        new1[i] = input[i];
                    }
                    for(int i=2;i<input.length;i++){
                        new2[i-2] = input[i];
                    }
                    for(int i=1;i<input.length-1;i++){
                        new3[i-1] = input[i];
                    }
                    return Math.max(Math.max(find(new1),find(new2)),find(new3));
                }
            }
            else{
                int[] new1 = new int[input.length-1];
                int[] new2 = new int[input.length-1];
                for(int i=0;i<input.length-1;i++){
                    new1[i] = input[i];
                }
                for(int i=1;i<input.length;i++){
                    new2[i-1] = input[i];
                }
                return Math.max(find(new1),find(new2));
            }
        }
    }
    
    

    2.动态规划

           上述递归解法存在大量重复计算,会超时。使用动态规划求解:
    (1)构建DP[i],长度为length,初始化全为0。i表示关注的字符串长度-1(-1方便编程)
    (2)由于字串长度必为偶数,则DP[i]=DP[i-1],i-1为奇数(即偶数位与上一奇数位相同)
    (3)对于DP[j],j为偶数,其取值范围为DP[i-1]~i+1(上限为字符串长度:i+1,下限为上一轮结果):
           a.整个字符串是否满足条件,满足则返回字符串长度:L=i+1,否则观察长度为L=L-2的子串是否满足
           b.对于每个L<i+1,只需观察两种情况是否满足:



           输入为1538023时构建DP的例子:



           代码(将调用find改为调用DP):
    import java.util.Scanner;
    
    public class SymSubstr {
        public static void main(String args[]){
            Scanner sc = new Scanner(System.in);
            int casesnum = sc.nextInt();
            sc.nextLine();
            while(casesnum>0){
                String temp = sc.nextLine();
                int[] input = new int[temp.length()];
                for(int i=0;i<input.length;i++){
                    input[i] = Integer.parseInt(temp.charAt(i)+"");
                }
                int result = DP(input);
                System.out.println(result);
                casesnum --;
            }
        }
        public static int DP(int[] input){
            int[] dp = new int[input.length];
            for(int i=0;i<dp.length;i++)
                dp[i] = 0;
            for(int i=1;i<input.length;i++){
                if(i%2 == 0)
                    dp[i] = dp[i-1];
                else{
                    //判断整个字符串是否满足
                    int sum1 = 0;
                    int sum2 = 0;
                    for(int j=0;j<=i/2;j++)
                        sum1 += input[j];
                    for(int j=i/2+1;j<=i;j++)
                        sum2 += input[j];
                    if (sum1 == sum2)
                        dp[i] = i+1;
                    else{
                        //不满足时,若上一轮的结果是整个字符串的长度,则可以不用计算。因为i-1是此时的下限
                        if(dp[i-1] == i-1)
                            dp[i] = i-1;
                        else{
                            for (int j=i-1;j>dp[i-2];j-=2){
                                //从i-1开始,按照长度递减判断是否存在子字符串
                                //sum3,sum4用于判断情况1,sum5,sum6用于判断情况2
                                int sum3 = 0;
                                int sum4 = 0;
                                int sum5 = 0;
                                int sum6 = 0;
                                //情况1
                                for(int k=i-j+1;k<i-j+1+j/2;k++)
                                    sum3 += input[k];
                                for(int k=i-j+1+j/2;k<i+1;k++)
                                    sum4 += input[k];
                                //情况2
                                for(int k=i-j;k<i-j+j/2;k++)
                                    sum5 += input[k];
                                for(int k=i-j+j/2;k<i;k++)
                                    sum6 += input[k];
                                if(sum3 == sum4 || sum5 == sum6) {
                                    dp[i] = j;
                                    break;
                                }
                            }
                            //若未能在到达下限之前找到答案,则答案为下限
                            if(dp[i] == 0)
                                dp[i] = dp[i-2];
                        }
                    }
                }
            }
            return dp[input.length-1];
        }
    }
    

    相关文章

      网友评论

          本文标题:对称子字符串

          本文链接:https://www.haomeiwen.com/subject/zrdpjqtx.html