字符串与hash(一)

之前有一种普遍使用的字符串hash:
hash[i+1]=(hash[i]\cdot base+s[i])MOD(mod)

可以有效地处理字符串的子串:

再者:还有可以代替KMP的hash:

hash=(hash\cdot base+s[i])MOD(mod)

+

hasht=(hasht\cdot base-s[i]\cdot tmp+s[i+strlen(s)])MOD(mod)

//tmp=\prod _{i=1}^{strlen(s)-1}base

现在我们从一道题目入手(SPOJ-EPALIN):

题意:

对给定字符串S,求以S为前缀的、长度最小的回文串并输出它

网上由两种解法:

一、KMP+逆字符串

二、hash+回文

我还有一种解法:马拉车+标记以S[LEN-1]为结尾的最长回文串长度的左端点

HASH回文:

1.回文的特点:

假设我们有一个回文串:

S_i,S_{i+1}.....S_{n-2},S_{n-1}

根据回文串特点:

我们有:(条件一)

S_i=S_{n-1}

S_{i+1}=S_{n-2}

..

..

首先,从一般的hash式子,我们有:(式子一)

hash1=(hash1*base+s[i])MOD(mod)//i: len-1 \Rightarrow 0

之后,简化式子,我们有:(式子二)

hash1=S_i+S_{i+1}\cdot base+...+S_{n-2}\cdot base^{n-2}+S_{n-1}\cdot base^{n-1}

又因为:有条件一:
所以:hash1=S_{n-1}+S_{n-2}*base+...+S_{i+1}\cdot *base^{n-2}+S_i\cdot base^{n-1}式子二)

我们令式子二的值为hash2

所以有了等价关系:

 hash1=hash2

ORZ.....

CODE:

#include 
#include 
#include 
typedef unsigned long long ull;
const int MAXN = 100000+100;
const int prime = 107;
const int mod = 1e9+7;
int n;
char s[MAXN];
int main()
{
    while(~scanf("%s",s))
    {
        n=strlen(s);
        ull pow=1;
        ull start=0;
        ull a1=0,a2=0;
        for(int i=n-1;i>=0;--i)
        {
            a1=(a1*prime+s[i])%mod;
            a2=(a2+pow*s[i])%mod;
            //printf("%d %d\n",a1,a2);
            if(a1==a2)
                start=i;
            pow=(pow*prime)%mod;
        }
        for(int i=0;i=0;--i)
            putchar(s[i]);
        printf("\n");
    }
}

 

你可能感兴趣的:(字符串,HASH)