Master of Both

在这里插入图片描述

题意:

给你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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宇智波一打七~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值