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×(n−1)×(n−2)×...×(n−k+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(1≤k≤n), 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 nn and kkare 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^6106letters.
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个字符串,和k个字符串组成的s,求s这随意选出的k个字符串中的位置。
解题思路:容易想到是将字符串排序后存在map里,然后就能得到每个字符串排序后的位置。
根据位置就能得到该字符串的位置。
该位置为 sigma(i,0,len-1)((b[i]-S(b[i])-1)*A(n-k,n-i))%mod;
b[i]-1为小于b[i]的个数S(b[i])当前位之前用过的比b[i]小的数的个数。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
#define lwob(x) x&-x
#define LL long long
const LL mod = 1e9+7;
const int N= 1000005;
string a[1000005];
int b[1000005];
LL qpow(LL a,LL k)
{
LL tm=1;
while(k)
{
if(k&1)
tm=(tm*a)%mod;
k>>=1;
a=(a*a)%mod;
}
return tm;
}
int c[N];
void add(int x)
{
while(x<=N)
{
c[x]+=1;
x+=lwob(x);
}
}
LL S(int p)
{
LL ans=0;
while(p)
{
ans+=c[p];
p-=lwob(p);
}
return ans;
}
LL f[N];
LL ni[N];
void init()
{
f[0]=1;
for(int i=1;i<=N;i++)f[i]=(i*f[i-1])%mod;
ni[N]=qpow(f[N],mod-2);
for(int i=N-1;i>=0;i--)ni[i]=(ni[i+1]*(i+1))%mod;
}
LL A(int n,int m)
{
return (f[m]*((ni[n])%mod))%mod;
}
int tot;
struct node
{
int id;
int t[26];
void init()
{
id=0;
memset(t,0,sizeof(t));
}
}tree[N];
void Ins(string s,int cnt)
{
int now=0;
for(int i=0;i<s.size();i++)
{
int p=s[i]-'a';
if(tree[now].t[p]==0)
{
tree[now].t[p]=++tot;
tree[tot].init();
}
now=tree[now].t[p];
}
tree[now].id=cnt;
}
void query(string s,int &cnt)
{
int now=0;
int be=0;
for(int i=0;i<s.size();i++)
{
int p=s[i]-'a';
now=tree[now].t[p];
if(tree[now].id!=0)
{
b[cnt++]=tree[now].id;
now=0;
}
}
if(tree[now].id!=0)
b[cnt++]=tree[now].id;
}
int main()
{
int n,k;
cin>>n>>k;
init();
for(int i=1;i<=n;i++)cin>>a[i];
sort(a+1,a+1+n);
tot=0;
for(int i=1;i<=n;i++)
{
Ins(a[i],i);
}
string s;
cin>>s;
int cnt=1;
query(s,cnt);
LL ans=0;
for(int i=1;i<cnt;i++)
{
ans+=((b[i]-S(b[i])-1)*A(n-k,n-i))%mod;
add(b[i]);
}
cout<<(ans+1)%mod<<endl;
}