CF985F (2020.3.12训练C题)

Description:
You are given a string s of length n consisting of lowercase English letters.

For two given strings s and t, say S is the set of distinct characters of s and T is the set of distinct characters of t. The strings s and t are isomorphic if their lengths are equal and there is a one-to-one mapping (bijection) f between S and T for which f(si) = ti. Formally:

f(si) = ti for any index i,
for any character there is exactly one character that f(x) = y,
for any character there is exactly one character that f(x) = y.
For example, the strings “aababc” and “bbcbcz” are isomorphic. Also the strings “aaaww” and “wwwaa” are isomorphic. The following pairs of strings are not isomorphic: “aab” and “bbb”, “test” and “best”.

You have to handle m queries characterized by three integers x, y, len (1 ≤ x, y ≤ n - len + 1). For each query check if two substrings s[x… x + len - 1] and s[y… y + len - 1] are isomorphic.

Input:
The first line contains two space-separated integers n and m (1 ≤ n ≤ 2·105, 1 ≤ m ≤ 2·105) — the length of the string s and the number of queries.

The second line contains string s consisting of n lowercase English letters.

The following m lines contain a single query on each line: xi, yi and leni (1 ≤ xi, yi ≤ n, 1 ≤ leni ≤ n - max(xi, yi) + 1) — the description of the pair of the substrings to check.

Output:
For each query in a separate line print “YES” if substrings s[xi… xi + leni - 1] and s[yi… yi + leni - 1] are isomorphic and “NO” otherwise.

题意:
给定一个长度为n的字符串,和m次起点分别为l和r的长度为len的合法与否询问,结果输出YES或NO(即从s[l]到s[l+len-1]的子串和从s[r]到s[r+len-1]的子串是否合法映射)

我们可以将利用哈希函数将原串构造成01串,进制为base(自己定),定义一个hashh二维数组,
hashh[i][j](比如hash[i][1]表示第i个位置是字母a的哈希值,如果是a,该位置为1,不是为0)

比如aabbc和cceef两个子串,因为如果映射合法,必然a对应c,b对应e,c对应f

所以对两个子串分别从a~z的26种情况计算哈希值并存入a[26]和b[26],排序后,如果映射合法,两个数组一定每个位置一一对应相等,有一处不同则不合法

ac代码如下

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;

const ll base = 131, maxn = 2e5 + 5, mod = 1e9 + 5;
ll n, m;
char s[maxn];
ll sum[maxn];
ll hashh[maxn][30];//比如hashh[i][1]表示第i个字符为a的哈希值
ll l, r, len;

void init()//初始化hashh和sum数组
{
	for (ll i = 1; i <= n; i++)
	{
		for (ll j = 1; j <= 26; j++)
		{
			hashh[i][j] = (hashh[i-1][j] * base % mod + ll(s[i] == 'a' + j - 1)) % mod;
		}
	}
	sum[0] = 1;
	for (ll i = 1; i <= n; i++)
	{
		sum[i] = sum[i - 1] * base % mod;
	}
}

bool judge()
{
	ll a[27], b[27];
	for (int i = 1; i <= 26; i++)
	{
		a[i] = (hashh[l + len - 1][i] - hashh[l - 1][i] * sum[len] % mod + mod) % mod;
		b[i] = (hashh[r + len - 1][i] - hashh[r - 1][i] * sum[len] % mod + mod) % mod;
	}
	sort(a + 1, a + 27);
	sort(b + 1, b + 27);
	for (int i = 1; i <= 26; i++)
	{
		if (a[i] != b[i])
			return 0;
	}
	return 1;
}

int main()
{
	cin >> n >> m;
	scanf("%s", s + 1);
	init();
	while(m--)
	{
		cin >> l >> r >> len;
		if (judge())
			cout << "YES" << endl;
		else
			cout << "NO" << endl;
	}
}
发布了16 篇原创文章 · 获赞 21 · 访问量 1328

猜你喜欢

转载自blog.csdn.net/rainbowower/article/details/104860653