字符串哈希

HASH

对于一个字符串s,令h[i] = h[i+1]*x + s[i] ,其中x是你自选的一个常数。令xp[i] = xp[i-1]*x

这样之后定义s的起点为下标i,长度为len的子串的哈希值为 h[i] - h[i+len]*xp[len] 。这个值与子串的位置,子串的内容,还有你自选的常数都有关系。哈希值使用unsigned long long(如果不是oi,可以使用int128的话当然更好) 不同子串的哈希值一定不会相同吗?不一定,但是相同的概率非常非常小。如果觉得不够保险可以分别选定两次x常数,双哈希来做。

//hash一般用来解决字符串判重/字符串匹配问题
//遇见不定长问题可通过二分+hash降低复杂度
//遇见定长字符串问题可通过尺取+hash来降低复杂度
//二维hash的时候尺取方法就是把之前不需要的都变为0再加上当前行,将匹配字符串整体下移,来验证hash值是否相等
//---------------------------------单Hash-----------------------
#include<string.h>
typedef unsigned long long ull;
const int maxn=1e5+5;
ull hash_[maxn],xp[maxn];
void init()
{
    xp[0]=1;
    for(int i=1;i<maxn;i++)
        xp[i]=xp[i-1]*13331;//这里13331玄学数字,大概可以随意换
    return ;
}
void make_hash(char str[])//处理出str的hash值
{
    int len=strlen(str);
    hash_[len]=0;
    for(int i=len-1;i>=0;i--)
    {
        hash_[i]=hash_[i+1]*13331+str[i]-'A'+1;
    }
    return ;
}
ull Get_hash(int i,int L)//得到起点为i,长度为L的子串的hash值
{
    return hash_[i]-hash_[i+L]*xp[L];
}
//---------------------------------双Hash-----------------------
ll hash_[2][maxn],xp[2][maxn];
const int Mod1 = 1000000007;
const int Mod2 = 19260817;
void init()
{
    xp[0][0]=1;
    for(int i=1;i<maxn;i++)
        xp[0][i]=xp[0][i-1]*13331%Mod1;
    xp[1][0]=1;
    for(int i=1;i<maxn;i++)
        xp[1][i]=xp[1][i-1]*1331%Mod2;
    return ;
}
void make_hash(char str[])
{
    int len=strlen(str);
    hash_[0][len]=0;
    hash_[1][len]=0;
    for(int i=len-1;i>=0;i--)
    {
        hash_[0][i]=(hash_[0][i+1]*13331%Mod1+str[i]-'A'+1)%Mod1;
        hash_[1][i]=(hash_[1][i+1]*1331%Mod2+str[i]-'A'+1)%Mod2;
    }
    return ;
}
pll Get_hash(int i,int L)//得到起点为i,长度为L的子串的hash值
{
    return pll((hash_[0][i]-hash_[0][i+L]*xp[0][L]%Mod1+Mod1)%Mod1,(hash_[1][i]-hash_[1][i+L]*xp[1][L]%Mod2+Mod2)%Mod2);
}
//---------------------------------多Hash-----------------------
//T是Hash次数
//hash_interval [a,b)
template <int T>
struct StringHash
{
  std::vector<std::vector<int>> ha, pw;
  std::vector<int> M;

  explicit StringHash(const std::string& s)
      : StringHash(std::vector<int>(s.begin(), s.end())) {}

  explicit StringHash(const std::vector<int>& vec)
  {
    pw = ha =
        std::vector<std::vector<int>>(T, std::vector<int>(vec.size() + 1));
    std::vector<int> C;
    for (int i = 0; i < T; i++)
    {
      pw[i][0] = 1;
      C.push_back(rand_int());
      M.push_back(rand_int());
    }
    for (int z = 0; z < T; z++)
    {
      for (size_t i = 0; i < vec.size(); ++i)
      {
        ha[z][i + 1] = (1LL * ha[z][i] * C[z] + vec[i]) % M[z],
                  pw[z][i + 1] = 1LL * pw[z][i] * C[z] % M[z];
      }
    }
  }

  // hash value of interval [a, b)
  std::vector<int> hash_interval(int a, int b)
  {
    std::vector<int> ret(T);
    for (int z = 0; z < T; z++)
    {
      ret[z] = (ha[z][b] - 1LL * ha[z][a] * pw[z][b - a] % M[z] + M[z]) % M[z];
    }
    return ret;
  }

  static int rand_int() 
  {
    static std::mt19937 gen((std::random_device())());
    static std::uniform_int_distribution<int> uid(1e8, 1e9);
    return uid(gen);
  }
};

字符串哈希算法是一种将字符串映射为数字的算法,常用于字符串的比较和匹配。在C++中,可以使用字符串哈希算法来加速字符串的比较操作。 引用\[1\]中的代码示例展示了一个使用字符串哈希算法的C++代码。该代码使用了前缀和数组和字符串数组来存储字符串,并通过计算哈希值来比较两个子串是否相等。其中,哈希值的计算使用了前缀和数组和幂运算。 引用\[2\]中的解释指出,使用字符串哈希的目的是为了比较字符串时不直接比较字符串本身,而是比较它们对应映射的数字。这样可以将子串的哈希值的时间复杂度降低到O(1),从而节省时间。 引用\[3\]中的代码示例也展示了一个使用字符串哈希算法的C++代码。该代码使用了前缀和数组和字符串数组来存储字符串,并通过计算哈希值来比较两个子串是否相等。与引用\[1\]中的代码类似,哈希值的计算也使用了前缀和数组和幂运算。 综上所述,字符串哈希算法是一种将字符串映射为数字的算法,常用于字符串的比较和匹配。在C++中,可以使用前缀和数组和幂运算来计算字符串哈希值,并通过比较哈希值来判断两个子串是否相等。 #### 引用[.reference_title] - *1* [C++算法题 # 33 字符串哈希](https://blog.csdn.net/weixin_44536804/article/details/123425533)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [字符串哈希(c++)](https://blog.csdn.net/qq_41829492/article/details/120980055)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [AcWing 841. 字符串哈希(C++算法)](https://blog.csdn.net/YSA__/article/details/108453403)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值