Hash~

简介: Hash~

image.jpeg


优势:任意给定一段区间[L,R]可以用O(1)的时间算出来

#include <iostream>
#include <string.h>
using namespace std;
typedef unsigned long long ull;
const int N = 1000010;
const int base = 131;
char str[N];
ull h[N];
int main()
{
    scanf("%s",str + 1);
    //算每个前缀的哈希值
    int n = strlen(str + 1);
    for(int i = 1;i <= n;i++)
    {
        h[i] = h[i - 1] * base + str[i] - 'a' + 1;
    }
    for(int i = 1;i <= n;i++)
    {
        printf("%llu\n",h[i]);
    }
    return 0;
}
//abc
//1
//133
//17426

算任意两段的哈希值的代码:

求某两段是不是一样的,分别求hash值判等

#include <iostream>
#include <string.h>
using namespace std;
typedef unsigned long long ull;
const int N = 1000010;
const int base = 131;
char str[N];
ull h[N],p[N];
ull get(int l,int r)
{
    return h[r] - h[l - 1] * p[r - l + 1];
}
int main()
{
    scanf("%s",str + 1);
    //算每个前缀的哈希值
    int n = strlen(str + 1);
    p[0] = 1;
    for(int i = 1;i <= n;i++)
    {
        h[i] = h[i - 1] * base + str[i] - 'a' + 1;
        p[i] = p[i - 1] * base;
    }
    int m;
    cin>>m;
    while(m--)
    {
        int l,r;
        cin>>l>>r;
        cout<<get(l,r)<<endl;
    }
    return 0;
}
/*
abcabcabc
3
1 3
17426
4 6
17426
7 9
17426
*/
兔子与兔子

60.png

由于数据比较大,接收时选择scanf,与上面代码就这不一样。【效率快】

#include <iostream>
#include <string.h>
using namespace std;
typedef unsigned long long ull;
const int N = 1000010;
const int base = 131;
char str[N];
ull h[N],p[N];
ull get(int l,int r)
{
    return h[r] - h[l - 1] * p[r - l + 1];
}
int main()
{
    scanf("%s",str + 1);
    //算每个前缀的哈希值
    int n = strlen(str + 1);
    p[0] = 1;
    for(int i = 1;i <= n;i++)
    {
        h[i] = h[i - 1] * base + str[i] - 'a' + 1;
        p[i] = p[i - 1] * base;
    }
    int m;
    cin>>m;
    while(m--)
    {
        int l1,r1,l2,r2;
        scanf("%d %d %d %d",&l1,&r1,&l2,&r2);
        if(get(l1,r1) == get(l2,r2))
            puts("Yes");
        else
            puts("No");
    }
    return 0;
}
回文子串的最大长度

上海自来水来自海上

61.png

左边的正序 == 右边的逆序

首先,回文串分为两大类:长度是奇数abcba,长度是偶数abba。

①技巧

②枚举中点

③二分半径,一个长度,如果一样就扩大长度,否则缩小长度。


技巧:

abcba --> a#b#c#b#a 奇数个数

abba --> a#b#b#a 也变成奇数个数

s个字母 补上 s-1个字母 变成 2s - 1 (奇数个呗)

#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;
typedef unsigned long long ULL;
const int N = 2000010, base = 131;
char str[N];
ULL hl[N], hr[N], p[N];
ULL get(ULL h[], int l, int r)
{
    return h[r] - h[l - 1] * p[r - l + 1];
}
int main()
{
    int T = 1;
    while (scanf("%s", str + 1), strcmp(str + 1, "END")) //调用这个函数,判断有没有遇到END,如果有就结束。逗号表达式,用逗号隔开的语句,返回值,只看最后一个语句的返回值 **细节**
    {
        int n = strlen(str + 1);
        for (int i = n * 2; i > 0; i -= 2)
        {
            str[i] = str[i / 2];
            str[i - 1] = 'z' + 1;
        }
        n *= 2;
        p[0] = 1;
        for (int i = 1, j = n; i <= n; i ++, j -- )//i,j分别是正序,逆序
        {
            hl[i] = hl[i - 1] * base + str[i] - 'a' + 1;
            hr[i] = hr[i - 1] * base + str[j] - 'a' + 1;
            p[i] = p[i - 1] * base;
        }
        int res = 0;
        for (int i = 1; i <= n; i ++ )
        {
            int l = 0, r = min(i - 1, n - i);
            while (l < r)
            {
                int mid = l + r + 1 >> 1;
                if (get(hl, i - mid, i - 1) != get(hr, n - (i + mid) + 1, n - (i + 1) + 1)) r = mid - 1;//注意端点值的确定,自己举俩例子判断找的对不对
                else l = mid;
            }
            if (str[i - l] <= 'z') res = max(res, l + 1);
            else res = max(res, l);
        }
        printf("Case %d: %d\n", T ++, res);
    }
    return 0;
}
后缀数组

62.png

63.png

/*
ponoiiipoi
10 i
9 oi
8 poi
7 ipoi
6 iipoi
5 iiipoi
4 oiiipoi
3 noiiipoi
2 onoiiipoi
1 ponoiiipoi
输出字典序最小的……
输出排名为 i 的后缀与排名为 i-1 的后缀,把二者的最长公共前缀的长度记为 Height[i] 
*/ 
#include <iostream>
#include <algorithm>
#include <string.h>
#include <limits.h>
using namespace std;
typedef unsigned long long ULL;
const int N = 300010, base = 131;
int n;
char str[N];
ULL h[N], p[N];
int sa[N];
int get(int l, int r)
{
    return h[r] - h[l - 1] * p[r - l + 1];
}
int get_max_common_prefix(int a, int b)
{
    int l = 0, r = min(n - a + 1, n - b + 1);
    while (l < r)
    {
        int mid = l + r + 1 >> 1;
        if (get(a, a + mid - 1) != get(b, b + mid - 1)) r = mid - 1;
        else l = mid;
    }
    return l;
}
bool cmp(int a, int b)
{
    int l = get_max_common_prefix(a, b);
    int av = a + l > n ? INT_MIN : str[a + l];
    int bv = b + l > n ? INT_MIN : str[b + l];
    return av < bv;
}
int main()
{
    scanf("%s", str + 1);
    n = strlen(str + 1);
    p[0] = 1;
    for (int i = 1; i <= n; i ++ )
    {
        h[i] = h[i - 1] * base + str[i] - 'a' + 1;
        p[i] = p[i - 1] * base;
        sa[i] = i;
    }
    sort(sa + 1, sa + 1 + n, cmp);
    for (int i = 1; i <= n; i ++ ) printf("%d ", sa[i] - 1);
    puts("");
    for (int i = 1; i <= n; i ++ )
        if (i == 1) printf("0 ");
        else printf("%d ", get_max_common_prefix(sa[i - 1], sa[i]));
    puts("");
    return 0;
}
所有和前缀和有关的下标都从1开始!
相关文章
|
SQL 开发框架 安全
C#编程与多线程处理
【4月更文挑战第21天】探索C#多线程处理,提升程序性能与响应性。了解C#中的Thread、Task类及Async/Await关键字,掌握线程同步与安全,实践并发计算、网络服务及UI优化。跟随未来发展趋势,利用C#打造高效应用。
355 3
python基础14题(入门必看)
python基础14题(入门必看)
python基础14题(入门必看)
|
5月前
|
机器学习/深度学习 小程序 数据挖掘
Multi-Agent 的灵活编排之路
本文探讨了Copilot 3.0架构中规划模块结合DeepSeek R1强化学习(GRPO)的实践,重点分析多智能体架构下大模型如何灵活调度多个智能体解决实际问题。文章从背景、问题分析、Planning角色、难点、效果对比到解决方案进行了深入讲解,并通过实验现象展示了有无思考过程对模型性能的影响。结果显示,GRPO训练后推理长度显著降低,准确率提升7.4个百分点,同时解决了复杂问题与简单问题处理间的平衡问题。
469 11
Multi-Agent 的灵活编排之路
|
7月前
|
SQL 安全 数据库
win10 安装 sql server2012
安装 SQL Server 2012 是许多开发者使用数据库的第一步。主要步骤包括:下载并运行安装程序,接受许可条款,选择功能(如数据库引擎服务),配置实例和服务器设置,设置身份验证模式,完成安装并进行测试。建议安装 SQL Server Management Studio (SSMS) 进行管理和维护,确保数据安全。
312 3
|
IDE 测试技术 API
使用京东API接口适用于的环境及验证调用合法性的方法
在电商领域,京东API接口支持商品信息查询、订单处理等功能。开发者需确保在稳定服务器端环境使用,选择合适编程语言及框架,并具备足够网络带宽处理能力。开发环境应配备IDE或代码编辑器及所需库。测试环境需充分验证API稳定性与可靠性。合法性验证包括:正确使用App Key和App Secret进行鉴权;掌握签名规则并在请求中添加签名;遵守请求频率限制;理解并遵循数据使用协议。遵循这些指导原则可保证API调用的合法性和稳定性。
|
网络协议 Linux
Linux如何查询端口被占用?
在Linux环境中,查询端口占用可使用`netstat`、`lsof`和`ss`命令。`netstat -tulnp | grep 80`显示TCP/UDP监听端口,`lsof -i:80`列出使用80端口的进程,而`ss -tuln | grep 80`是`netstat`的现代替代选项。若需解决端口占用问题,先找出占用进程的ID,然后用`kill -9`命令终止它,或调整服务配置以避免冲突。
962 2
|
JSON 数据处理 数据格式
python 一个点运算符操作的字典库:DottedDict
python 一个点运算符操作的字典库:DottedDict
163 0
|
存储 NoSQL
TableStore: 海量结构化数据分层存储方案
### 前言 表格存储是阿里云自研分布式存储系统,可以用来存储海量结构化、半结构化的数据。表格存储支持高性能和容量型两种实例类型。高性能使用SSD的存储介质,针对读多写多的场景都有较好的访问延时。容量型使用的是SSD和SATA混合的存储介质。
9685 0
|
存储 前端开发 数据可视化
低代码平台实际解决了哪些问题?
低代码平台实际解决了哪些问题?
282 0
|
Go 索引
Go一分钟对接ElasticSearch实践
今天这篇分享:使用Go语言对接ElasticSearch实践。
577 0