CodeForces985F:Isomorphic Strings (字符串&hash)

题意:取出字符串Str里的两个串S,T,问对应位置的的字符在否有一一映射关系。

hash:对于每个字符s=‘a’-‘z’,我们任意找一个i,满足Si==s,(代码里用lower_bound在区间找到最小的位置i)其对应的字符为Ti==t。然后我们判断这段区间里s的hash值是否等于t的hash值。不难证明26个字母都满足时对应hash相同时,才有一一映射关系。(但是不明白我的自然溢出的hash版本为什么错了,但是mod(1e9+7)的版本对了?

#include<bits/stdc++.h>
using namespace std;
#define ll unsigned long long
const int maxn=200010;
const int seed=131;
const int Mod=1e9+7;
ll Hash[26][maxn],g[maxn];
int a[26][maxn],N;
char c[maxn];
ll gethash(int chr,int x,int Len)
{
    return ((Hash[chr][x+Len-1]-Hash[chr][x-1]*g[Len]%Mod)+Mod)%Mod;
}
bool check(int x,int y,int Len)
{
    int i,pos;
    for(i=0;i<26;i++){
        pos=lower_bound(a[i]+1,a[i]+1+a[i][0],x)-a[i];
        if(pos>a[i][0]||a[i][pos]>x+Len-1) continue;
        if(gethash(i,x,Len)!=gethash(c[y-x+a[i][pos]]-‘a‘,y,Len))  return false;
    }
    return true;
}
int main()
{
    int Q,x,y,len,i,j;
    scanf("%d%d",&N,&Q);
    scanf("%s",c+1); g[0]=1;
    for(i=1;i<=N;i++){
        g[i]=g[i-1]*seed%Mod;
        for(j=0;j<26;j++)
           Hash[j][i]=(Hash[j][i-1]*seed+(c[i]-‘a‘==j))%Mod;
        a[c[i]-‘a‘][++a[c[i]-‘a‘][0]]=i;
    }
    while(Q--){
        scanf("%d%d%d",&x,&y,&len);
        if(check(x,y,len)) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}

下面是自然溢出的has版本

#include<bits/stdc++.h>
using namespace std;
#define ll unsigned long long
const int maxn=200010;
const int seed=131;
ll Hash[26][maxn],g[maxn];
int a[26][maxn],N;
char c[maxn];
ll gethash(int chr,int x,int Len)
{
    return Hash[chr][x+Len-1]-Hash[chr][x-1]*g[Len];
}
bool check(int x,int y,int Len)
{
    int i,pos;
    for(i=0;i<26;i++){
        pos=lower_bound(a[i]+1,a[i]+1+a[i][0],x)-a[i];
        if(pos>a[i][0]||a[i][pos]>x+Len-1) continue;
        if(gethash(i,x,Len)!=gethash(c[y-x+a[i][pos]]-‘a‘,y,Len))  return false;
    }
    return true;
}
int main()
{
    int Q,x,y,len,i,j;
    scanf("%d%d",&N,&Q);
    scanf("%s",c+1); g[0]=1;
    for(i=1;i<=N;i++){
        g[i]=g[i-1]*seed;
        for(j=0;j<26;j++)
           Hash[j][i]=Hash[j][i-1]*seed+(c[i]-‘a‘==j);
        a[c[i]-‘a‘][++a[c[i]-‘a‘][0]]=i;
    }
    while(Q--){
        scanf("%d%d%d",&x,&y,&len);
        if(check(x,y,len)) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}

#include<bits/stdc++.h>using namespace std;#define ll unsigned long longconst int maxn=200010;const int seed=131;const int Mod=1e9+7;ll Hash[26][maxn],g[maxn];int a[26][maxn],N;char c[maxn];ll gethash(int chr,int x,int Len){return ((Hash[chr][x+Len-1]-Hash[chr][x-1]*g[Len]%Mod)+Mod)%Mod;}bool check(int x,int y,int Len){int i,pos;for(i=0;i<26;i++){pos=lower_bound(a[i]+1,a[i]+1+a[i][0],x)-a[i];if(pos>a[i][0]||a[i][pos]>x+Len-1) continue;if(gethash(i,x,Len)!=gethash(c[y-x+a[i][pos]]-‘a‘,y,Len))  return false;}return true;}int main(){int Q,x,y,len,i,j;scanf("%d%d",&N,&Q);scanf("%s",c+1); g[0]=1;for(i=1;i<=N;i++){g[i]=g[i-1]*seed%Mod;for(j=0;j<26;j++)    Hash[j][i]=(Hash[j][i-1]*seed+(c[i]-‘a‘==j))%Mod;a[c[i]-‘a‘][++a[c[i]-‘a‘][0]]=i;}while(Q--){scanf("%d%d%d",&x,&y,&len);if(check(x,y,len)) printf("YES\n");else printf("NO\n");}return 0;}

原文地址:https://www.cnblogs.com/hua-dong/p/9074020.html

时间: 2024-11-13 09:00:52

CodeForces985F:Isomorphic Strings (字符串&hash)的相关文章

Power Strings POJ - 2406,字符串hash

题目链接:POJ - 2406 题目描述 定义两个字符串s1和s2的乘积s1*s2为将s1和s2连结起来得到的字符串. 例如:s1="xy",s2="z",那么s1*s2="xyz". 由此可以定义s1的幂次:s1^0="",s1^n=s1*s1^(n-1),n>0. 输入 输入包含多组测试数据. 每组数据由一行构成,包含一个字符串s. 输入数据以"."结束. 输出 对于每组输入数据输出一行,找出最大

leetcode_205题——Isomorphic Strings(用的map)

Isomorphic Strings Total Accepted: 5891 Total Submissions: 24698My Submissions Question Solution Given two strings s and t, determine if they are isomorphic. Two strings are isomorphic if the characters in s can be replaced to get t. All occurrences

leetcode 204/187/205 Count Primes/Repeated DNA Sequences/Isomorphic Strings

一:leetcode 204 Count Primes 题目: Description: Count the number of prime numbers less than a non-negative number, n 分析:此题的算法源码可以参看这里,http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes 代码: class Solution { public: int countPrimes(int n) { // 求小于一个数n的素数个

LeetCode:Isomorphic Strings

1.题目名称 Isomorphic Strings(同构的字符串) 2.题目地址 https://leetcode.com/problems/isomorphic-strings/ 3.题目内容 英文: Given two strings s and t, determine if they are isomorphic. Two strings are isomorphic if the characters in s can be replaced to get t. All occurre

hdu 3973 字符串hash+线段树

http://acm.hdu.edu.cn/showproblem.php?pid=3973 Problem Description You are given some words {Wi}. Then our stupid AC will give you a very long string S. AC is stupid and always wants to know whether one substring from S exists in the given words {Wi}

205. Isomorphic Strings - LeetCode

Question 205. Isomorphic Strings Solution 题目大意:判断两个字符串是否具有相同的结构 思路:构造一个map,存储每个字符的差,遍历字符串,判断两个两个字符串中相同位置字符的差是否相同 Java实现: public boolean isIsomorphic(String s, String t) { Map<String, Integer> map = new HashMap<>(); for (int i=0; i<s.length(

hdu 1880 魔咒词典(字符串hash)

题目链接:hdu 1880 魔咒词典 题意: 给你一个10w的词典,让你输出对应的字段. 题解: map暴力存字符串肯定会卡内存,这里用BKDR字符串hash一下,用map映射一下. 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;++i) 3 using namespace std; 4 typedef unsigned long long ull; 5 6 const int N=1e5+7,seed=133

【二分答案+智障的字符串hash】BZOJ2946-[Poi2000]公共串(Ranklist倒一达成!!!!!)【含hash知识点】

[题目大意] 给出几个由小写字母构成的单词,求它们最长的公共子串的长度. [字符串hash的小笔记] hash[i]=(hash[i-1]*p+idx(s[i]))%mod,idx为映射值,一般a..z映射1..26: 习惯上,p取一个6到8位的素数即可,mod一般取大素数 1e9+7(1000000007)或1e9+9(1000000009). hash[i]=(hash[i-1]*p+idx(s[i]))%mod 表示第 i 个前缀的hash值,是一个hash的前缀和,那么,要求S[l…r]

hdu4821 String 字符串hash(bkdrhash)

题意:给定m,l,一个字符串str. 我们定义一个子串为"recoverable"串 当 1.长度为 M*L 2.把这个好串分成M段,每段长度为L,且每段各不相同. 求"recoverable"串的个数,串相同位置不同也算不同. 思路:预处理数组hash,hash[i]表示从i位置到尾的字符串hash值.这里数组为unsigned long long型,因为可以自动取模.然后枚举 前l个位置,每次向后翻滚(将前一个长度为l的段hash值从map中去除,将翻滚后新出现

字符串hash + 二分答案 - 求最长公共子串 --- poj 2774

Long Long Message Problem's Link:http://poj.org/problem?id=2774 Mean: 求两个字符串的最长公共子串的长度. analyse: 前面在学习后缀数组的时候已经做过一遍了,但是现在主攻字符串hash,再用字符串hash写一遍. 这题的思路是这样的: 1)取较短的串的长度作为high,然后二分答案(每次判断长度为mid=(low+high)>>1是否存在,如果存在就增加下界:不存在就缩小上界): 2)主要是对答案的判断(judge函数