• hash,ACM集训


                                    840. 模拟散列表

    目录

                                    840. 模拟散列表

    输入格式

    输出格式

    数据范围

    输入样例:

    输出样例:

     解析:

                                    841. 字符串哈希

    输入格式

    输出格式

    数据范围

    输入样例:

    输出样例:

     解析:字符串前缀hash法

                            4696. 最长回文

    输入格式

    输出格式

    数据范围

    输入样例:

    输出样例:

     解析:字符串hash;二分+hash;队列和栈;Manacher算法


    840. 模拟散列表 - AcWing题库

    维护一个集合,支持如下几种操作:

    1. I x,插入一个数 x;
    2. Q x,询问数 x 是否在集合中出现过;

    现在要进行 N 次操作,对于每个询问操作输出对应的结果。

    输入格式

    第一行包含整数 N,表示操作数量。

    接下来 N 行,每行包含一个操作指令,操作指令为 I xQ x 中的一种。

    输出格式

    对于每个询问指令 Q x,输出一个询问结果,如果 x 在集合中出现过,则输出 Yes,否则输出 No

    每个结果占一行。

    数据范围

    1≤N≤105
    −109≤x≤109

    输入样例:
    1. 5
    2. I 1
    3. I 2
    4. I 3
    5. Q 2
    6. Q 5
    输出样例:
    1. Yes
    2. No

     解析:

    拉链法代码

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. #include
    13. #include
    14. using namespace std;
    15. typedef long long LL;
    16. const int N = 1e5 + 3;
    17. int n;
    18. int h[N], e[N], ne[N], ind;
    19. void Insert(int a) {
    20. int t = (a % N + N) % N;
    21. e[ind] = a, ne[ind] = h[t], h[t] = ind++;
    22. }
    23. int find(int a) {
    24. int t = (a % N + N) % N;
    25. for (int i = h[t]; i != -1; i = ne[i])
    26. if (e[i] == a)
    27. return 1;
    28. return 0;
    29. }
    30. int main() {
    31. cin >> n;
    32. char op[2];
    33. int t;
    34. memset(h, -1, sizeof(h));
    35. for (int i = 1; i <= n; i++) {
    36. scanf("%s%d", op, &t);
    37. if (op[0] == 'I') {
    38. Insert(t);
    39. }
    40. else {
    41. if (find(t))
    42. cout << "Yes" << endl;
    43. else
    44. cout << "No" << endl;
    45. }
    46. }
    47. return 0;
    48. }

    开放寻址法 通常数组大小要开到2到3倍(经验之谈)

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. #include
    13. #include
    14. using namespace std;
    15. typedef long long LL;
    16. const int N = 3e5 + 5,null=0x3f3f3f3f;
    17. int n;
    18. int h[N];
    19. int find(int a) {
    20. int k = (a % N + N) % N;
    21. while (h[k]!=null&&h[k]!=a) {
    22. k++;
    23. if (k == N)k = 0;
    24. }
    25. return k;
    26. }
    27. int main() {
    28. cin >> n;
    29. char op[2];
    30. int t;
    31. memset(h, 0x3f, sizeof(h));
    32. for (int i = 1; i <= n; i++) {
    33. scanf("%s%d", op, &t);
    34. int k = find(t);
    35. if (op[0] == 'I') {
    36. h[k] = t;
    37. }
    38. else {
    39. if (h[k] == null)
    40. cout << "No" << endl;
    41. else
    42. cout << "Yes" << endl;
    43. }
    44. }
    45. return 0;
    46. }

                                    841. 字符串哈希

     841. 字符串哈希 - AcWing题库

    给定一个长度为 n 的字符串,再给定 m 个询问,每个询问包含四个整数 l1,r1,l2,r2,请你判断 [l1,r1] 和 [l2,r2] 这两个区间所包含的字符串子串是否完全相同。

    字符串中只包含大小写英文字母和数字。

    输入格式

    第一行包含整数 n 和 m,表示字符串长度和询问次数。

    第二行包含一个长度为 n 的字符串,字符串中只包含大小写英文字母和数字。

    接下来 m 行,每行包含四个整数 l1,r1,l2,r2,表示一次询问所涉及的两个区间。

    注意,字符串的位置从 1 开始编号。

    输出格式

    对于每个询问输出一个结果,如果两个字符串子串完全相同则输出 Yes,否则输出 No

    每个结果占一行。

    数据范围

    1≤n,m≤105

    输入样例:
    1. 8 3
    2. aabbaabb
    3. 1 3 5 7
    4. 1 3 6 8
    5. 1 2 1 2
    输出样例:
    1. Yes
    2. No
    3. Yes

     解析:字符串前缀hash法

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. #include
    13. #include
    14. using namespace std;
    15. typedef long long LL;
    16. typedef unsigned long long ULL;
    17. const int N = 1e5 + 5,P=131;
    18. int n, m;
    19. char str[N];
    20. ULL h[N], p[N];
    21. ULL get(int l, int r) {
    22. return h[r] - h[l-1] * p[r - l + 1];
    23. }
    24. int main() {
    25. scanf("%d%d%s", &n, &m, str + 1);
    26. p[0] = 1;
    27. for (int i = 1; i <= n; i++) {
    28. p[i] = p[i - 1] * P;
    29. h[i] = h[i - 1] * P + str[i];
    30. }
    31. int l1, r1, l2, r2;
    32. while (m--) {
    33. scanf("%d%d%d%d", &l1, &r1, &l2, &r2);
    34. if (get(l1, r1) == get(l2, r2)) {
    35. cout << "Yes" << endl;
    36. }
    37. else
    38. cout << "No" << endl;
    39. }
    40. return 0;
    41. }

                            4696. 最长回文

    4696. 最长回文 - AcWing题库

    给出一个只由小写英文字符 a,b,c…y,z 组成的字符串 S,求 S 中最长回文串的长度。

    回文就是正反读都是一样的字符串,如 aba, abba 等。

    输入格式

    输入有多组测试数据,不超过 120 组。

    每组输入为一行小写英文字符 a,b,c…y,z 组成的字符串 S

    两组数据之间由空行隔开(该空行不用处理)。

    输出格式

    每一行一个整数 x,对应一组数据,表示该组数据的字符串中所包含的最长回文长度。

    数据范围

    1≤|S|≤110000

    输入样例:
    1. aaaa
    2. abab
    输出样例:
    1. 4
    2. 3

     解析:字符串hash;二分+hash;队列和栈;Manacher算法

    字符串hash法:

    将两个hash数组,一个正着hash,另一个反着hash

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. #include
    13. #include
    14. using namespace std;
    15. typedef long long LL;
    16. typedef unsigned long long ULL;
    17. const int N = 1e5 + 1e4 + 5,P=131;
    18. char str[N];
    19. ULL h[N],h1[N], p[N];
    20. ULL get(int l, int r, ULL* arr) {
    21. return arr[r] - arr[l - 1] * p[r - l + 1];
    22. }
    23. int main() {
    24. while (scanf("%s", str + 1) != EOF) {
    25. int n = strlen(str + 1);
    26. p[0] = 1;
    27. for (int i = 1,j=n; i <= n;j--, i++) {
    28. p[i] = p[i - 1] * P;
    29. h[i] = h[i - 1] * P + str[i];
    30. h1[i] = h1[i - 1] * P + str[j];
    31. }
    32. int len1 = 1, len2 = 1;
    33. for (int i = 1; i <= n; i++) {
    34. while (i - len1 >= 1 && i + len1 <= n && (get(i - len1, i, h) == get(n-i-len1+1,n-i+1, h1))) {
    35. len1++;
    36. }
    37. while (i - len2 >= 0 && i + len2 <= n && (get(i - len2 + 1, i, h) == get(n-i-len2+1,n-i, h1))) {
    38. len2++;
    39. }
    40. }
    41. cout << max(len2 * 2 - 2, len1 * 2 - 1) << endl;
    42. }
    43. return 0;
    44. }

    这是我一开始的错误代码:

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. #include
    13. #include
    14. using namespace std;
    15. typedef long long LL;
    16. typedef unsigned long long ULL;
    17. const int N = 1e5 + 1e4 + 5, P = 131;
    18. ULL h[N], h1[N], p[N];
    19. string str, str1;
    20. ULL get(int l, int r, ULL* arr) {
    21. return arr[r] - arr[l] * p[r - l];
    22. }
    23. int main() {
    24. while (cin >> str) {
    25. int n = str.length();
    26. str1 = str;
    27. reverse(str1.begin(), str1.end());
    28. str.insert(0, " ");
    29. str1.insert(0, " ");
    30. p[0] = 1;
    31. for (int i = 1; i <= n; i++) {
    32. p[i] = p[i - 1] * P;
    33. h[i] = h[i - 1] * P + str[i];
    34. h1[i] = h1[i - 1] * P + str1[i];
    35. }
    36. int mx = 1;
    37. for (int i = 0; i <= n; i++) {
    38. for (int j = i; j <= n; j++) {
    39. if (get(i, j, h) == get(n - j, n - i, h1))
    40. mx = max(mx, j - i);
    41. }
    42. }
    43. cout << mx << endl;
    44. }
    45. return 0;
    46. }

    这个代码最大的缺陷就是这个代码是从左到右延申,到实际上如果从中间像两头延申的话当出现不满足的情况时就和以确定以i为中心的最长的回文子串的长度了,没有必要继续判断以i为中心是否有更长的回文子串了

  • 相关阅读:
    C# OpencvSharp异常FileNotFoundException具体解决办法
    重装系统后没声音如何解决
    ubuntu 查询mysql的用户名和密码 ubuntu查看username
    【C补充】单向链表的反转(4种方法)
    C语言——三子棋游戏
    Golang——从入门到放弃
    日志框架体系整理( 基础 )
    Mac Vue 项目上传到阿里云服务器及 nginx
    ESP32设备通信-LoRa通信
    Vue30 自定义指令 函数式 对象式
  • 原文地址:https://blog.csdn.net/Landing_on_Mars/article/details/132954074