蓝桥杯 Java 括号序列

本算法需要把问题分解成三步:

第一步:算出 ((() 填充 ( 的方案

第二步:算出 ((() 填充 ) 的方案

第三步:把两个方案相乘

第二步可以把原方案当成将 ((() 逆转成 ())) 再填充 ( ,这样就可以重复第一步用的算法

第一步中做动态规划

fij表示第i个右括号左边填充j个左括号的可用的方案数

fij = fi-10\~j的方案和

cnt1表示需要的总左括号数

f11\~cnt1方案都只有一个

f10如果不成立方案数为0否则为1

注意:

  1. 这个算法可以利用优化简化复杂度,具体相见代码
  2. fij对j有要求,j最小是当前右括号个数减去当前位置的左边的括号数(这个在遍历数组的时候利用前缀和求解),也就是所需的左括号的最小(如果为负最小值为0)。
  3. 注意要取余数,最后相乘之后也需要求余
java 复制代码
import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改
// 先算一次只加左括号的方案
// 再算只加右括号的方案(镜像对称即可)
// 两方案相乘
public class Main{
  static long M = 1000000007;
  static char[] cs;
  
  public static void main(String[] args){
    Scanner sc = new Scanner(System.in);
    cs = sc.nextLine().toCharArray();
    long ans = clac();
    int n = cs.length;
    for(int i = 0,j = n-1;i < j;i++,j--){
      char temp = cs[i];
      cs[i] = cs[j];
      cs[j] = temp;
    }
    for(int i = 0;i < n;i++){
      if(cs[i] == '(')cs[i] = ')';
      else cs[i] = '(';
    }
    ans *= clac();// 反转后再来一遍
    System.out.println(ans%M);
  }

  public static long clac(){
    int[] sum = new int[5001];
    int cnt1 = 0;
    int cnt2 = 0;
    int n = 0;
    long[][] f = new long[5001][5001];// 遍历第i个,添加j个左括号的结果
    int ri = 1;
    for(char c:cs){
      if(c == '('){
        sum[ri]++;
        cnt2++;
      }else{
        ri++;
        n++;
        if(cnt2 == 0){
          cnt1++;
        }else{
          cnt2--;
        }
      }
    }
    for(int i = 1;i <= n;i++){// SUM转为前缀和
      sum[i] += sum[i-1];
    }
    for(int j = 0;j <= cnt1;j++){
      f[1][j] = 1;
    }
    if(sum[1] == 0){// 如果第一个右括号前没有左括号,不加括号的方案无效
      f[1][0] = 0;
    }
    // for(int i = 2;i <= n; i++){// 遍历右括号
    //   for(int j = Math.max(0,i-sum[i]);j <= cnt1;j++){// 加多少左括号,注意有下限
    //     for(int k = 0;k <= j;k++){
    //       f[i][j] = (f[i][j] + f[i-1][k])%M;
    //     }
    //   }
    // }
    // 优化上文的算法
    for(int i = 2;i <= n; i++){// 遍历右括号
      long[] ne = new long[cnt1+1];
      ne[0] = f[i-1][0];
      for(int k = 1;k <= cnt1;k++){
        ne[k] = ne[k-1] + f[i-1][k];
        ne[k] %= M;
      }
      for(int j = Math.max(0,i-sum[i]);j <= cnt1;j++){// 加多少左括号,注意有下限
        f[i][j] += ne[j];
      }
    }
    return f[n][cnt1];
  }
}
相关推荐
招聘风控观察38 分钟前
招聘质量管理是什么?招聘质量的定义与评价口径完整解释
职场和发展
金銀銅鐵2 小时前
[Java] 用 GUI 展示 EnumSet 增减元素时的内部变化(上)
java·后端·ai编程
福建佰胜张工2 小时前
SMC 薄型气爪 MHF2-16D1 深度解析:平行开闭、低剖面结构在自动化装配中的选型与落地
java·服务器·安全·自动化
catoop2 小时前
API Key 设计与安全生成方案:结构拆解、数据库设计与 Java 实现
java·数据库·安全
system_error_x3 小时前
SpringBoot 集成 Thymeleaf 简洁入门
java·spring boot·后端
驭渊的小故事3 小时前
Spring AI Alibaba 实战:从maven依赖治理到声明式工具调用
java·人工智能·spring
Elastic 中国社区官方博客4 小时前
我们如何通过 70 多个拉取请求,将 OpenTelemetry Java agent 迁移到 invokedynamic
java·大数据·开发语言·elasticsearch·搜索引擎·全文检索·es
tyn1884 小时前
记录本地安装nacos服务的方法及异常
java·开发语言
步行cgn4 小时前
Spring MVC 视图机制的核心接口与类
java·开发语言·后端·spring·mvc
y1su5 小时前
Leetcode 字符串模板
java·数据结构·算法·leetcode·职场和发展·动态规划