题意:
给你n个字符串,然后给你m个字典序排列,问你在每一种字典序排列的情况下这n个字符串所组成的逆序对数量是多少
思路:
因为字符串中只有26个字母,然后我们可以考虑两个字符串相比的时候哪两个字符起到了关键性的作用,比如说abc和abd,就是第三个字母d起到了关键性作用,那么就是b -> d,最多有26*26种关系,我们可以记录一下每种关系出现了多少次,但是这里需要注意,abc和abcd这两个字符串的话他们相比的两个关键字母,对于第一个字符串来说是没有的,我们可以再加一个字母,比这些字母都小,然后每个字符串的后面都加上这么一个字符来封底,那么就tire树一边建一边初始化,然后每个字典顺序都遍历所有关系就行了,下面看代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+10;
int idx,a[N+N][27],sum[N+N];
char s[N];
long long cnt[1000];
void insert(){
int k;
int r = 0;
for(int i=0;s[i];i++){
k = s[i] - 'a' + 1;
if(!a[r][k]) a[r][k] = ++idx;
for(int j=0;j<27;j++){
if(j == k) continue;
cnt[(j+1)*27+k+1] += sum[a[r][j]];
}
sum[a[r][k]] ++;
r = a[r][k];
}
}
int mp[33];
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%s",s);
int n = strlen(s);
s[n] = 'a' - 1;
s[n+1] = 0;
insert();
}
char str[30];
while(m--){
scanf("%s",str+1);
str[0] = 'a' - 1;
for(int i=0;str[i];i++) mp[str[i]-'a'+1] = i;
long long ans = 0;
for(int i=0;i<27;i++){
for(int j=0;j<27;j++){
int t = (i+1)*27+j+1;
if(mp[i] > mp[j]){
ans += cnt[t];
}
}
}
printf("%lld\n",ans);
}
return 0;
}