字符串——字符串hash的子串hash值

常用的进制hash满足一些性质所有可以O(1) 查询子串或者减去某些位置的子串的hash值。

	scanf("%d", &n);
    scanf("%s", a+1);
    p[0] = 1, h[0] = 0;
    for(int i = 1; i <= n; i++){
        h[i] = h[i-1]*base + a[i] - 'A';
        p[i] = p[i-1]*base;
    }

1.查询子串的hash值

比如ABACD的子串ACD的hash值为h[5]-h[3-1]*p[5-3+1]

inline unsigned long long get_hash(int l, int r)
{
        return h[r] - h[l-1] * p[r-l+1];
}

证明:
h a s h ( 1 , r ) = i = 1 r a [ i ] b a s e r i hash(1,r) = \sum_{i=1}^r a[i]*{base^{r-i}}
h a s h ( l , r ) = i = l r a [ i ] b a s e r l hash(l, r) = \sum_{i=l}^r a[i]*{base^{r-l}}
= i = 1 r a [ i ] b a s e r i i = 1 l 1 a [ i ] b a s e l 1 i b a s e r l + 1 = \sum_{i=1}^r a[i]*{base^{r-i}} - \sum_{i=1}^{l-1} a[i]*{base^{l-1-i}}*{base^{r-l+1}}
= h a s h ( 1 , r ) h a s h ( 1 , l 1 ) b a s e r l + 1 = hash(1, r) - hash(1, l-1)*{base^{r-l+1}}

2.查询子串再减去子串中的一个字符

unsigned long long get_s(int l, int r, int x)
//去掉x位置的字符得到的字符串的hash值
{
    return get_hash(l, x-1) * p[r-x] + get_hash(x+1, r);
}

3.查询两个子串拼接的hash

unsigned long long get_s1_s2(int l1, int r1, int l2, int r2){
    return get_hash(l1, r1) * p[r2-l2+1] + get_hash(l2, r2);
}

发布了23 篇原创文章 · 获赞 6 · 访问量 830

猜你喜欢

转载自blog.csdn.net/wxy2635618879/article/details/103968837