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:
- Two strings are the same length
- The number of character types in s is the same as that in t
- 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; }