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

Posted Roni

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

 

以上是关于ACM-ICPC北京赛区(2017)网络赛2后缀数组+Java//不会的主要内容,如果未能解决你的问题,请参考以下文章

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

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

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

ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛 hihocoder #1586 : Minimum-区间查询最值求区间两数最小乘积+单点更新-线段树(结构体版)

hihoCoder 1632 Secret Poems(ACM-ICPC北京赛区2017网络同步赛)

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