模板总结——基于哈希的LCP问题

问题引入

求第i位开始的后缀和第j位开始的后缀的最长公共前缀的长度?

高度数组&&RMQ

求出高度数组lcp,假设rank[i]小于rank[j],那么后缀i和后缀j的LCP值等于min{lcp[rank[i],lcp[rank[i+1],…lcp[rank[j]-1}.
预处理RMQ即可O(1)查询LCP值。但由于是预处理RMQ,无法动态回答LCP回答。也就是说一旦题目中有对字符串修改的操作,则此方法无法解决。

基于哈希的LCP

给每一个子串一个哈希值,这样子串改变时只需对应地修改哈希值即可。
定h(i)表示后缀S[i…]的哈希值。
定义hash(i,L)表示以i为起始位置、长度为L的子串的哈希值。

h(n-1)=s[n-1] 边界
h(i)=h(i+1)*x+s[i] 递推
一般地,

h[i]=s[i]+s[i+1]*x+s[i+2]*x^2+...+s[n-1]*x^(n-1-i);

hash(i,L)的哈希值定义如下

hash(i,L)=s[i]+s[i+1]*x+s[i+2]*x^2+...+s[i+L-1]*x^(L-1)

推导后,

hash(i,L)=h[i]-h[i+L]*x^L;

所以预处理h和x^L后就可以在常数时间内计算出hash(i,L)。hash值可能很大,这里用unsigned long long去存,这样在算术运算时会自然溢出,相当于模2^64.

解决问题:
二分答案L,如果hash(i,L)==hash(j,L),那么就认为以LCP(i,j)>=len.

模板

const int x=123;//随便取一个x
unsigned long long h[maxn],xp[maxn];
int n;
string s;

void get_hxp()
{
    n=s.size();
    h[n]=0;
    for(int i=n-1;i>=0;i--)
        h[i]=h[i+1]*x+s[i]-'a';
    xp[0]=1;
    for(int i=1;i<=n;i++)
        xp[i]=xp[i-1]*x;
}
unsigned long long Hash(int i,int L)
{
    return h(i)-h(i+L)*xp[L];
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值