[hiho1579] Reverse Suffix Array [ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛 B]

题意

给出一个字符串后缀的排序,求可能的原串个数
例如”banana”的后缀排序为[6,4,2,1,5,3]
因为

6:a
4:ana
2:anana
1:b
5:na
3:nana

题解

以样例为例

Index : 1 2 3 4 5 6
String: b a n a n a
Rank  : 4 3 6 2 5 1
Pos   : 6 4 2 1 5 3

Index为字符串各个字符的编号,String为原串,Rank为对应Index为开头的后缀的排名,Pos为对应Index排名的后缀的位置(例如排名为 1 的后缀位置是 6 ,故 Pos(1)=6 )。
对于任意两个 Rank 相邻的后缀 i i+1 ,通过比较这两个后缀去掉首字符之后的后缀的 rank 可以确定 i i+1 这两个位置的字符是否可以相同,即比较 Rank(Pos(i)+1) Rank(Pos(i+1)+1) ,如果 Rank(Pos(i)+1)>Rank(Pos(i+1)+1) i i+1 两位置字符不能相同且 String(i)<String(i+1) ,否则,相同字符与其后缀相连, Rank(i) 将会大于 Rank(i+1) ,这改变了后缀的 Rank ,是不合法的;如果 Rank(Pos(i)+1)<Rank(Pos(i+1)+1) String(i)String(i+1)
统计一遍有多少个 Rank(Pos(i)+1)>Rank(Pos(i+1)+1) 的位置,设其为 m 。如果 m26 则合法串个数为0(因为字符集大小为26)。
现在从 Rank 第一的串开始填字符,只有之前提到的那些位置是必须要比之前字符大的,其它都可以大于等于之前字符。而这不方便计算答案,现在将必须要增加的位置消去,设 h=25m ,则相当于字符集大小为 h+1 ,每个 Rank 的字符都可以大于等于比它小的 Rank 的字符。那么这个的答案通过组合数学的隔板法得到为

Cnn+h

爆long long,需要高精度运算,可以使用python或java

代码

# by ztx
N = 100005

T = int(input())
pos = [0 for i in range(N)]
rank = [0 for i in range(N)]

for iii in range(T):
    n = int(input())
    Str = input().split() # python2: raw_input()
    for i in range(1,n+1):
        pos[i] = int(Str[i-1])
        rank[pos[i]] = i
    if n == 1:
        print("26")
        continue
    m = 0
    rank[n+1] = 0
    for i in range(2,n+1):
        if rank[pos[i-1]+1] > rank[pos[i]+1]:
            m = m+1
    h = 25-m
    if h < 0:
        print("0")
        continue
    ans = 1
    for i in range(n+1,n+h+1):
        ans = ans * i
    for i in range(1,h+1):
        ans = ans // i
    print(ans)

你可能感兴趣的:(OJ-hiho,数学-排列组合)