开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第15天,点击查看活动详情
K - Master of Both
Professor Hui-Bot is the master of string theory and advanced data structures, so he came up with an interesting problem. Given a sequence of strings consisting of only lowercase English letters, how many inversions are there in this sequence when the strings are compared by lexicographical order?
As the most extraordinary student of Hui-Bot, Putata and Budada mastered superb string theory and advanced data structure skills respectively, and they solved this problem together with ease. However, there are different parallel universes, where the characters in the alphabet are not appearing in the original order.
Formally, the alphabet in each universe is a string, which is a permutation of the lowercase English letter, denoting the order each character appears.
A string is lexicographically smaller than a string if and only if one of the following holds:
is a prefix of , but ; in the first position where and differ, the string has a letter that appears earlier in the alphabet than the corresponding letter in . The number of inversions in a sequence of length is the number of ordered pairs such that , .
Please help Putata and Budada in each universe to solve the problem.
中文大意
给我们n个字符串然后输入q个英文字母的全排列定义现在的字典序根据这个排序求出现在的逆序对
解法
对于一个字符串我们只需要找出第一个不同的两个位置,然后比较一下即可
Code
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e6 + 10;
ll a[27][27] ,b[27], c[N][27], tot, cnt[N], res;
char s[N];
void insert(char *s) {
int n = strlen(s + 1);
int p = 0;
for(int i = 1; i <= n; i++) {
int x = s[i] - 'a';
for(int j = 0; j < 26; j++) {
if(j != x && c[p][j]) a[j][x] += cnt[c[p][j]];
}
if(!c[p][x]) c[p][x] = ++tot;
p = c[p][x];
cnt[p] ++;
}
for(int j = 0; j < 26; j++) {
if(c[p][j]) {
res += cnt[c[p][j]];
}
}
}
void solve() {
int n, m; scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++) {
scanf("%s", s + 1);
insert(s);
}
while(m -- ) {
scanf("%s",s + 1);
int k = strlen(s + 1);
for(int i = 1; i <= k; i++) b[s[i] - 'a'] = i;
ll ans = 0;
for(int i = 0; i < 26; i++)
for(int j = 0; j < 26; j++) {
if(b[j] < b[i]) ans += a[i][j];
}
printf("%lld\n", ans + res);
}
}
int main()
{
int T = 1;
// scanf("%d", &T);
while(T--) solve();
return 0;
}