[trie树]Master of Both 2022年ICPC杭州站K

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 nn 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 qq 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 2626 lowercase English letter, denoting the order each character appears.

A string aa is lexicographically smaller than a string bb if and only if one of the following holds:

  • aa is a prefix of bb, but a≠ba≠b;
  • in the first position where aa and bb differ, the string aa has a letter that appears earlier in the alphabet than the corresponding letter in bb.

The number of inversions in a sequence aa of length nn is the number of ordered pairs (i,j)(i,j) such that 1≤i

Please help Putata and Budada in each universe to solve the problem.

Input

The first line of the input contains two integers n,qn,q (1≤n≤5×1051≤n≤5×105, 1≤q≤5×1041≤q≤5×104), denoting the length of the sequence.

For the following nn lines, the ii-th line contains a string sisi (1≤|si|≤1061≤|si|≤106). It is guaranteed that the string consists of only lowercase English letters, and ∑i=1n|si|≤106∑i=1n|si|≤106.

For the following qq lines, each line contains a string tt, denoting the alphabet in one universe. It is guaranteed that tt is a permutation of 2626 lowercase English letters.

Output

Output qq lines, denoting the answer in qq universes.

Example

input

5 3
aac
oiputata
aaa
suikabudada
aba
abcdefghijklmnopqrstuvwxyz
qwertyuiopasdfghjklzxcvbnm
aquickbrownfxjmpsvethlzydg

output

4
3
4

题意: 给出n个字符串,以及q次询问,每次询问给出一个字母之间的大小顺序,问在该顺序下这n个字符串的逆序对个数。

分析: 两字符串比较大小需要看第一个不同的字符,对于任意两字符串可以找到它们第一个不同的字符,设它们为x和y,那么可以用一个二维数组记录一下,令rel[x][y]++,这里的rel[i][j]就表示由i和j大小决定的字符串的对数,如果在某个询问中i的字典序大于j的字典序,因为在记录的时候又是按照i所在字符串出现在j所在字符串之前,那么逆序对个数就可以加上rel[i][j],最终扫描一遍rel数组就能够得到答案。最后注意因为字典序判断的时候还可能出现abc和abcd的情况,所以每个字符串最后都需要添加一个比较小的字符。

rel数组的更新需要用到trie树,一遍建树一遍更新即可,能决定两字符串大小的字符只会出现在trie树上的分叉节点上,所以可以根据这个特点来更新rel数组。

具体代码如下:

#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

char s[1000005];
int idx, son[2000005][30];
long long cnt[2000005];
long long rel[30][30]; 

void insert(){
	int now = 0;
	for(int i = 1; s[i]; i++){
		int t = s[i]-'a'+1;
		if(!son[now][t]) son[now][t] = ++idx;
		for(int j = 0; j <= 26; j++){
			if(j == t) continue;
			rel[j][t] += cnt[son[now][j]];
		}
		now = son[now][t];
		cnt[now]++;
	}
}

signed main(){
	int n, q;
	scanf("%d%d", &n, &q);
	for(int i = 1; i <= n; i++){
		scanf("%s", s+1);
		int len = strlen(s+1);
		s[len+1] = 'a'-1;
		s[len+2] = '\0';
		insert();
	} 
	char s[30];
	int mp[30];
	mp[0] = 0;
	for(int i = 1; i <= q; i++){
		scanf("%s", s+1);
		int len = strlen(s+1);
		for(int j = 1; j <= len; j++)
			mp[s[j]-'a'+1] = j;
		long long ans = 0;
		for(int j = 0; j <= 26; j++)
			for(int k = 0; k <= 26; k++){
				if(mp[j] > mp[k]) 
					ans += rel[j][k];
			}
		printf("%lld\n", ans);
	}
    return 0;
}

你可能感兴趣的:(题解,算法)