ACM-ICPC 2018 南京赛区网络预赛 Skr 马拉车+字符串hash+hash表

题目链接:Skr

题意,求不同的回文串的和。

题解:马拉车的时候当找到一个新的回文串时,判断这个回文串的hash值是否在hashmap中,没有就加入然后ans加上这段值,有就不管

#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
using namespace std;
const int base=23;
const int N=2e6+100;
const int mod=1e9+7;
struct hash
{
    char s[N];
    ull h[N],qp[N];
    ll p[N],len,val[N];
    void init()
    {
        h[0]=val[0]=0;
        qp[0]=p[0]=1;
        len=strlen(s+1);
        for(int i=1;i<=len;i++)
        {
            p[i]=p[i-1]*10%mod;
            qp[i]=qp[i-1]*base;
            h[i]=h[i-1]*base+s[i];
            val[i]=(1LL*val[i-1]*10%mod+s[i]-'0')%mod;
        }
    }
    ull get_hash(int l,int r)
    {
        return h[r]-h[l-1]*qp[r-l+1];
    }
    int get_val(int l,int r)
    {
        return ((val[r]-val[l-1]*p[r-l+1]%mod)%mod+mod)%mod;
    }
}ac;
int mx,len[N],x;
ll ans;
const int HASH = 1000007;
const int maxn=1e7+7;
struct hashmap{
    ll a[maxn];
    int head[HASH],nxt[maxn],sz;
    void init(){
        memset(head,-1,sizeof(head));
        sz = 0;
    }
    bool find(ull val){
        int tmp = (val%HASH + HASH) % HASH;
        for(int i = head[tmp] ; ~i ; i = nxt[i]){
            if(val == a[i]) return true;
        }
        return false;
    }
    void add(ull val){
        int tmp = (val%HASH + HASH) % HASH;
        if(find(val)) return;
        a[sz] = val;
        nxt[sz] = head[tmp];
        head[tmp] = sz ++;
    }
}ap;
void ins(int l,int r)
{
    ull h=ac.get_hash(l,r);
    if(!ap.find(h))
    {
        ap.add(h);
        ans+=ac.get_val(l,r);
        ans%=mod;
    }
}
int main(){
    scanf("%s",ac.s+1);
    ac.init();
    ap.init();
    //int mx=0,x=0;
    for(int i=1;i<=ac.len;i++)
    {
        ins(i,i);
        if(mx>i)len[i]=min(mx-i,len[2*x-i]);
        while(i+len[i]+1<=ac.len&&ac.s[i+len[i]+1]==ac.s[i-len[i]-1])
        {
            ins(i-len[i]-1,i+len[i]+1);
            len[i]++;
        }
        if(i+len[i]>mx)
        {
            mx=i+len[i];x=i;
        }
    }
    mx=x=0;
    memset(len,0,sizeof len);
    ap.init();
    for(int i=2;i<=ac.len;i++)
    {
        if(mx>i)len[i]=min(mx-i+1,len[2*x-i]);
        while(i+len[i]<=ac.len&&ac.s[i+len[i]]==ac.s[i-len[i]-1])
        {
           ins(i-len[i]-1,i+len[i]);
            len[i]++;
        }
        if(i+len[i]-1>mx)
        {
            mx=i+len[i]-1;x=i;
        }
    }
    printf("%lld\n",ans);
    return 0;
}

 

posted @ 2018-10-04 20:08  lhclqslove  阅读(334)  评论(0编辑  收藏  举报