Codeforces - 985f isomorphic strings (string hash)

Keywords: iOS

Title Link: Click to view

Main idea: first of all, the isomorphic string is specified. If string s and string t are isomorphic strings, they must meet the following requirements:

  1. Two strings are the same length
  2. The number of character types in s is the same as that in t
  3. Each letter in s has a corresponding in t, and must be a one-to-one mapping relationship

For example, wwaaa and aaccc are isomorphic strings, aababc and bbcbcz are also isomorphic strings

Now I will give m queries. Each query will give x y len. The length of the query is len. Are the strings starting with X and Y isomorphic to each other

Problem analysis: I didn't think of how to do it at the beginning. The hint is that there is no good way after hashing. After reading the solution of the problem, I feel that I have learned the ingenious way

Back to this topic, because each letter is relatively independent, we hash 26 letters. That is, after reading the string, we preprocess the Hash[i][j], which means the location is I, and the current letter is j. after preprocessing, we only need to find one letter from the substring y for each letter of substring x If all 26 letters can find the mapping relationship without conflict, it means they are isomorphic strings

I think it might be clearer to look at the code directly

Finally, for a single hash, the base=131, mod = ull Ou Max that I have been using will be hack ed out.. However, with base=23333333, mod = 99999998, AC will be successful. Then write hash and use this set of base

Code:

#include<iostream>
#include<cstdio> 
#include<string>
#include<ctime>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<cmath>
#include<sstream>
#include<unordered_map>
using namespace std;

typedef long long LL;

typedef unsigned long long ull;

const int inf=0x3f3f3f3f;

const int N=2e5+100;

const int base=2333333;

const int mod=999999998;

string s;

int n,m;

ull Hash[N][26],f[N];

int nx[N][26],pos[26];//nx[i][j]: the position containing the ith position followed by the letter j for the first time 

void init()
{
	f[0]=1;
	for(int i=1;i<=n;i++)//Preprocess the hash value of each letter
	{
		f[i]=f[i-1]*base%mod;
		for(int j=0;j<26;j++)
			Hash[i][j]=(Hash[i-1][j]*base+(s[i]==char(j+'a')))%mod;
//The hash value of each bit here is non-zero or one, which is used to indicate whether the current position is the current letter
	}
	for(int j=0;j<26;j++)
		pos[j]=n+1;
	for(int i=n;i>=1;i--)//Preprocessing nx array, simple dp
	{
		pos[s[i]-'a']=i;
		for(int j=0;j<26;j++)
			nx[i][j]=pos[j];
	}
}

ull get_hash(int l,int r,int alpha)
{
	return (Hash[r][alpha]-Hash[l-1][alpha]*f[r-l+1]%mod+mod)%mod;
}

bool solve(int x,int y,int len,int alpha)
{
	int pos=nx[x][alpha];//Find the corresponding letter in x
	if(pos>x+len-1)//If the letter does not exist in the description x, return true directly
		return true;
	pos+=y-x;//To the letter in y
	return get_hash(x,x+len-1,alpha)==get_hash(y,y+len-1,s[pos]-'a');//Determine whether hash values are equal
}

bool check(int x,int y,int len)
{
	for(int j=0;j<26;j++)//Enumerate whether each letter in substring x conflicts 
		if(!solve(x,y,len,j))
			return false;
	return true;
}

int main()
{
//	freopen("input.txt","r",stdin);
//	ios::sync_with_stdio(false);
	scanf("%d%d",&n,&m);
	cin>>s;
	s=" "+s;
	init();
	while(m--)
	{
		int x,y,len;
		scanf("%d%d%d",&x,&y,&len);
		if(check(x,y,len))
			puts("YES");
		else
			puts("NO");
	}
	
	
	
	
	
	
	
	
	
	return 0;
}

 

Published 536 original articles, won praise 16, visited 10000+
Private letter follow

Posted by Sphen001 on Sun, 19 Jan 2020 03:01:21 -0800