zoukankan      html  css  js  c++  java
  • CH1401 兔子与兔子【字符串】【HASH】

    1401 兔子与兔子 0x10「基本数据结构」例题

    描述

    很久很久以前,森林里住着一群兔子。有一天,兔子们想要研究自己的 DNA 序列。我们首先选取一个好长好长的 DNA 序列(小兔子是外星生物,DNA 序列可能包含 26 个小写英文字母),然后我们每次选择两个区间,询问如果用两个区间里的 DNA 序列分别生产出来两只兔子,这两个兔子是否一模一样。注意两个兔子一模一样只可能是他们的 DNA 序列一模一样。

    输入格式

    第一行一个 DNA 字符串 S。
    接下来一个数字 m,表示 m 次询问。
    接下来 m 行,每行四个数字 l1, r1, l2, r2,分别表示此次询问的两个区间,注意字符串的位置从1开始编号。
    其中 1 ≤ length(S), m ≤ 1000000

    输出格式

    对于每次询问,输出一行表示结果。如果两只兔子完全相同输出 Yes,否则输出 No(注意大小写)

    样例输入

    aabbaabb
    3
    1 3 5 7
    1 3 6 8
    1 2 1 2

    样例输出

    Yes
    No
    Yes

    来源

    罗翔宇,北京大学2014年数据结构与算法A(实验班)期末考试

    题意:

    比较一个字符串的两端区间内的子串是不是相同的

    思路:

    要注意的是

    之前在for的结束条件里写了i <= strlen(s+1),然后T了

    因为strlen是O(n)的,放在了for条件里的话就每次都做了一次O(N)

    虐狗宝典字符串Hash的知识点:

    字符串Hash函数把一个任意长度的字符串映射成一个非负整数,并且其冲突概率几乎为零。

    去以固定值P,把字符串看成P进制数,并分配一个大于0的数值,代表每种字符。取一个固定值M,求出该P进制数对M的余数,作为该字符串的Hash值。

    一般来说取P=131或P=13331。通常取M = 2^64,也就是直接使用unsigned long long存储这个Hash值,产生溢出时相当于自动对2^64取模。

    只要Hash值相同,我们就可以认为原字符串是相等的。

    上述Hash算法很难产生冲突,一般情况下完全可以用在题目的标准解答中。还可以多取一些恰当的P和M的值,多进行几组Hash运算。

    如果已知字符串S的Hash值为H(S),那么在S后添加一个字符c的新字符串的Hash值就是H(S+c)=(H(S)*P+val[c])modM

    如果已知字符串S的Hash值为H(S),字符串S+T的Hash值为H(S+T),那么字符串T的Hash值H(T)=(H(S+T) -H(S)*Plength(T))mod M

     1 #include <iostream>
     2 #include <set>
     3 #include <cmath>
     4 #include <stdio.h>
     5 #include <cstring>
     6 #include <algorithm>
     7 #include <map>
     8 using namespace std;
     9 typedef long long LL;
    10 #define inf 0x7f7f7f7f
    11 
    12 const int maxn = 1e6 + 5;
    13 char s[maxn];
    14 int m;
    15 int l1, r1, l2, r2;
    16 unsigned long long H[maxn], p[maxn];
    17 
    18 int main()
    19 {
    20     scanf("%s", s + 1);
    21     int n = strlen(s + 1);
    22     p[0] = 1;
    23     H[0] = 0;
    24     for(int i = 1; i <= n; i++){
    25         H[i] = H[i - 1] * 131 + (s[i] - 'a' + 1);
    26         p[i] = p[i - 1] * 131;
    27     }
    28     scanf("%d", &m);
    29     while(m--){
    30         scanf("%d%d%d%d", &l1, &r1, &l2, &r2);
    31         if(H[r1] - H[l1 - 1] * p[r1 - l1 + 1] == H[r2] - H[l2 - 1] * p[r2 - l2 + 1]){
    32             puts("Yes");
    33         }
    34         else{
    35             puts("No");
    36         }
    37     }
    38 
    39 
    40 }
  • 相关阅读:
    二级菜单
    eclipse高版本中EasyExplore的替换插件OpenExplore
    Python学习一
    原型编程的基本规则
    【CF671D】 Roads in Yusland(对偶问题,左偏树)
    【洛谷4542】 [ZJOI2011]营救皮卡丘(最小费用最大流)
    【洛谷4313】 文理分科(最小割)
    【洛谷4001】 [ICPC-Beijing 2006]狼抓兔子(最小割)
    【洛谷2057】 [SHOI2007]善意的投票(最小割)
    【洛谷2053】 [SCOI2007]修车(费用流)
  • 原文地址:https://www.cnblogs.com/wyboooo/p/9813428.html
Copyright © 2011-2022 走看看