Prefix Free Code 字典序

Consider nn initial strings of lower case letters, where no initial string is a prefix of any other initial string. Now, consider choosing kk of the strings (no string more than once), and concatenating them together. You can make this many such composite strings:

 

\displaystyle n \times (n - 1) \times (n - 2) \times . . . \times (n - k + 1)n×(n1)×(n2)×...×(nk+1)

 

Consider sorting all of the composite strings you can get via this process in alphabetical order. You are given a test composite string, which is guaranteed to belong on this list. Find the position of this test composite string in the alphabetized list of all composite strings, modulo 10^9 + 7109+7. The first composite string in the list is at position 11.

Input Format

Each input will consist of a single test case.

Note that your program may be run multiple times on different inputs.

Each test case will begin with a line with two integers, first nn and then k (1 \le k \le n)k(1kn), where nn is the number of initial strings, and kk is the number of initial strings you choose to form composite strings. The upper bounds of nnand kk are limited by the constraints on the strings, in the following paragraphs.

Each of the next nn lines will contain a string, which will consist of one or more lower case letters a..za..z. These are the nn initial strings. It is guaranteed that none of the initial strings will be a prefix of any other of the initial strings.

Finally, the last line will contain another string, consisting of only lower case letters a..za..z. This is the test composite string, the position of which in the sorted list you must find. This test composite string is guaranteed to be a concatenation of kk unique initial strings.

The sum of the lengths of all input strings, including the test string, will not exceed 10^6106 letters.

Output Format

Output a single integer, which is the position in the list of sorted composite strings where the test composite string occurs. Output this number modulo 10^9 + 7109+7.

样例输入1
5 3
a
b
c
d
e
cad
样例输出1
26
样例输入2
8 8
font
lewin
darko
deon
vanb
johnb
chuckr
tgr
deonjohnbdarkotgrvanbchuckrfontlewin
样例输出2
12451
题目来源

The North American Invitational Programming Contest 2018

 

先将n个字符串从小到大排下序,然后求下给定的字符串的排列是多少,然后就可以求出答案了。

 1 #include <bits/stdc++.h>
 2 #define ll long long
 3 #define lowbit(x) x&(-x)
 4 using namespace std;
 5 const int N = 1e6+10;
 6 const ll mod = 1e9+7;
 7 char str[N];
 8 ll a[N], c[N], ans = 1, cnt = 1;
 9 map<ll,ll> mp;
10 struct Nod{
11     ll is;
12     Nod *next[26];
13     Nod(){
14         is = 0;
15         for(int i = 0; i < 26; i ++){
16             next[i] = NULL;
17         }
18     }
19 };
20 
21 void update(int x, ll y){
22     while(x < N){
23         c[x] += y;
24         x += lowbit(x);
25     }
26 }
27 ll query(int x){
28     ll sum = 0;
29     while(x > 0){
30         sum += c[x];
31         x -= lowbit(x);
32     }
33     return sum;
34 }
35 void mkTrie(Nod *root,char *s, ll num){
36     Nod*p = root;
37     for(int i = 0; s[i]; i ++){
38         int a = s[i] - 'a';
39         if(p->next[a]==NULL)p->next[a] = new Nod;
40         p = p->next[a];
41     }
42     p->is = num;
43 }
44 void dfs(Nod *root) {
45     Nod *p = root;
46     for(int i = 0; i < 26; i ++) {
47         if(p->next[i] != NULL) {
48             dfs(p->next[i]);
49         } else if(p->is != 0) {
50             mp[p->is] = cnt++;
51             return;
52         }
53     }
54 }
55 void find(Nod *root, char *s, int k){
56     Nod* p = root;
57     for(int i = 0; s[i]; i ++){
58         int b = s[i]-'a';
59         p = p->next[b];
60         if(p->is != 0) {
61             ans = (a[k--]*(mp[p->is]-query(mp[p->is])-1)+ans)%mod;
62             update(mp[p->is],1);
63             p = root;
64         }
65     }
66 }
67 int main() {
68     ll n, k;
69     cin >> n >> k;
70     a[0] = 1;
71     a[1] = n-k+1;
72     for(ll i = 2; i <= k; i ++) {
73         a[i] = a[i-1]*(n+i-k)%mod;
74     }
75     Nod *root = new Nod;
76     for(int i = 1; i <= n; i ++) {
77         cin >> str;
78         mkTrie(root, str, i);
79     }
80     dfs(root);
81     cin >> str;
82     find(root,str,k-1);
83     printf("%lld\n",ans);
84     return 0;
85 }

 

转载于:https://www.cnblogs.com/xingkongyihao/p/9460806.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值