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; }