ACM-ICPC北京赛区(2017)网络赛2【后缀数组+Java//不会】

#1579 : Reverse Suffix Array

时间限制:1000ms

单点时限:1000ms

内存限制:256MB

描述

There is a strong data structure called "Suffix Array" which can effectively solve string problems.

Let S=s1s2...sn be a string and let S[i,j] denote the substring of S ranging from i to j. The suffix array A of S is now defined to be an array of integers providing the starting positions of suffixes of S in lexicographical order. This means, an entry A[i] is the starting position of the i-th smallest suffix in S and thus for all 1 < i ≤ n:  S[A[i-1], n] < S[A[i], n].

For example: the suffix array of “banana” is [6, 4, 2, 1, 5, 3].

Here comes another problem called "Reverse Suffix Array".

Given a suffix array, you need to figure out how many lower case strings are there whose suffix array is the same as the given suffix array.

输入

First line contains a positive number T which means the number of test cases.

For each test cases, first line contains a positive number N, the second line contains N integer(s) which indicates the suffix array A.

1 ≤ T ≤ 10, 1 ≤ N ≤ 100,000

1 ≤ A[i] ≤ N (i = 1...N)

输出

For each test case, output one line contains the answer. If no qualified string exists, output 0.

样例输入
1
5
4 3 2 5 1
样例输出
98280【题意】:已知后缀数组,求原串的可能情况数。【分析】:java,26^3 dp,http://blog.csdn.net/skywalkert/article/details/51731556(在 cdoj 上也有一个类似【代码】:

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.math.BigInteger;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        Task2 solver = new Task2();
        int testCount = Integer.parseInt(in.next());
        for (int i = 1; i <= testCount; i++)
            solver.solve(i, in, out);
        out.close();
    }

    static class Task2 {
        BigInteger C(int n, int m) {
            BigInteger ans = BigInteger.valueOf(1);
            for (int i = 1; i <= m; i++) {
                ans = ans.multiply(BigInteger.valueOf(n - i + 1));
            }
            for (int i = 2; i <= m; i++) {
                ans = ans.divide(BigInteger.valueOf(i));
            }
            return ans;
        }

        public void solve(int testNumber, InputReader in, PrintWriter out) {
            int n = in.nextInt();
            int[] a = new int[n + 1];
            int[] b = new int[n + 1];
            for (int i = 1; i <= n; i++) {
                a[i] = in.nextInt();
                b[a[i]] = i;
            }
            ArrayList<Integer> arr = new ArrayList<>();
            int now = 1;
            for (int i = 2; i <= n; i++) {
                if (a[i - 1] != n && (a[i] == n || b[a[i - 1] + 1] > b[a[i] + 1])) {
                    arr.add(now);
                    now = 1;
                } else {
                    now++;
                }
            }
            arr.add(now);
            if (arr.size() > 26) {
                out.println(0);
            } else {
                int sz = arr.size();
                BigInteger[][] dp = new BigInteger[sz + 1][27];
                for (int i = 0; i <= sz; i++) {
                    for (int j = 0; j <= 26; j++) {
                        dp[i][j] = BigInteger.valueOf(0);
                    }
                }
                dp[0][0] = BigInteger.valueOf(1);
                for (int i = 0; i < sz; i++) {
                    for (int j = 0; j < 26; j++) {
                        for (int k = 1; j + k <= 26; k++) {
                            dp[i + 1][j + k] = dp[i + 1][j + k].add(dp[i][j].multiply(C(arr.get(i) + k - 2, k - 1)));
                        }
                    }
                }
                // out.println(dp[sz][26]);
                BigInteger ans = BigInteger.valueOf(0);
                for (int i = 1; i <= 26; i++) {
                    ans = ans.add(dp[sz][i]);
                }
                out.println(ans);
            }
        }

    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

    }
}

809ms

时间: 2024-10-05 18:01:21

ACM-ICPC北京赛区(2017)网络赛2【后缀数组+Java//不会】的相关文章

hihoCoder 1578 Visiting Peking University 【贪心】 (ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛)

#1578 : Visiting Peking University 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 Ming is going to travel for n days and the date of these days can be represented by n integers: 0, 1, 2, -, n-1. He plans to spend m consecutive days(2 ≤ m ≤ n)in Beijing. Durin

ACM-ICPC北京赛区(2017)网络赛1【模拟+枚举+数组操作】

题目1 : Visiting Peking University 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 Ming is going to travel for n days and the date of these days can be represented by n integers: 0, 1, 2, …, n-1. He plans to spend m consecutive days(2 ≤ m ≤ n)in Beijing. During

hihoCoder 1584 Bounce 【数学规律】 (ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛)

#1584 : Bounce 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 For Argo, it is very interesting watching a circle bouncing in a rectangle. As shown in the figure below, the rectangle is divided into N×M grids, and the circle fits exactly one grid. The bouncing

ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛

题目1 : Visiting Peking University 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 Ming is going to travel for n days and the date of these days can be represented by n integers: 0, 1, 2, -, n-1. He plans to spend m consecutive days(2 ≤ m ≤ n)in Beijing. During

ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛 i题 Minimum(线段树)

描述 You are given a list of integers a0, a1, …, a2^k-1. You need to support two types of queries: 1. Output Minx,y∈[l,r] {ax?ay}. 2. Let ax=y. 输入 The first line is an integer T, indicating the number of test cases. (1≤T≤10). For each test case: The fi

ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛 题目9 : Minimum

时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 You are given a list of integers a0, a1, …, a2^k-1. You need to support two types of queries: 1. Output Minx,y∈[l,r] {ax?ay}. 2. Let ax=y. 输入 The first line is an integer T, indicating the number of test cases. (

hihocoder 1584 Bounce (数学 &amp;&amp; 规律) ACM-ICPC北京赛区2017网络赛

题意: 给定一副n*m的格子图, 问从左上角的点开始往右下角滑,碰到墙壁就反弹, 碰到角落就停止, 问恰好经过一次的格子有多少个. 如图,恰好经过一次的格子有39个. 分析: 首先要引入两个概念, "路径长","格子数". 路径长指的是整段路程的长度,如果走过同一个格子两次那么就算是2步. 格子数指的是整段路程经过的格子. 如果一个图是9*9(形如n*n)的, 那么就是从左上角一直到右下角, 走过的"路径长"恰好等于"格子数"

ACM-ICPC北京赛区(2017)网络赛_Minimum

题目9 : Minimum 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 You are given a list of integers a0, a1, -, a2^k-1. You need to support two types of queries: 1. Output Minx,y∈[l,r] {ax?ay}. 2. Let ax=y. 输入 The first line is an integer T, indicating the number of

hihocoder 1586 ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛-题目9 : Minimum【线段树】

https://hihocoder.com/problemset/problem/1586 线段树操作,原来题并不难..... 要求乘积最小只要求区间内最大值.最小值和绝对值小的数,再判断min,max正负就行了. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #define lson l,