Birthday Cake(双hash(具体模板)+逆元+排序)

swjtu—春季集训 - Virtual Judge (vjudge.net)

思路:

  • 把2个字符串组合在一起,在平分,看是否相同,按照原顺,切割时候,会出现要补字母的情况
  • 于是预处理 按照字符串长度排序,以此解决这个问题
  • 匹配的时候就利用双哈希+map处理就行了,
  • 注意 逆元的时候:快速腻,mod 双哈希是不同的mod,按照以往的写法容易写错。(这个错找了30min)

后记:

  • 写双哈希的时候,直接让变量名称大写,比较好写和检擦。
  • 按照进制的思想写hash,并且从左往右和从右往左写的时候是不一样的
  • 从左往右 代表着 数组第 i 位 : 以他为末尾的hash值,一共有 i 位(i从1开始算), 弄的时候直接  ha[i] x ba +s[i+1],(不用-'a')
  • 从右往左 代表着 数组第 i 位: 以他为开头到末尾的hash值, 弄的时候 ha[i+1+1]+ s[i+1]xpo[k], k为循环变量. (注意 i是 i+1 !!),开始的i 是leng-1;
  • 1e9+7 -- 61, 1e9+9 -- 97 // 有规律的记 利用97
#include <bits/stdc++.h>
using namespace std;
#define ri register int
#define M 400005

int n,m;
struct dain{
    string s;
    int val;
    bool operator <(const dain &t)const
    {
        return val<t.val;
    }
}p[M];

long long ksn(long long a,long long b,int mod)
{
    long long ans=1;
    while(b)
    {
        if(b&1) ans=ans*a%mod;
        b>>=1,a=a*a%mod;
    }
    return ans;
 } 
const int mod=1e9+7;
const int MOD=1e9+9;
long long ba=61;
long long BA=97;
long long po[M],PO[M];
long long inv[M],INV[M];

void init(){
    
    po[0]=1;PO[0]=1;
    inv[0]=1;INV[0]=1;
    for(ri i=1;i<=4e5;i++)
    {
        po[i]=po[i-1]*ba%mod;
        inv[i]=ksn(po[i],mod-2,mod);
        PO[i]=PO[i-1]*BA%MOD;
        INV[i]=ksn(PO[i],MOD-2,MOD);
    }
    
}
long long val[M],VAL[M];
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    
    cin>>n;
    for(ri i=1;i<=n;i++)
    {
        cin>>p[i].s;
        p[i].val=p[i].s.length();
    }
    
    sort(p+1,p+1+n);
    init();
    map<int,int> mp;
    map<int,int> MP;
    long long ans=0;
    for(ri ii=1;ii<=n;ii++)
    {
        
        for(ri i=0;i<p[ii].s.length();i++) // 真实i+1, 
        {
            val[i+1]=(val[i]*ba%mod+p[ii].s[i])%mod;
            VAL[i+1]=(VAL[i]*BA%MOD+p[ii].s[i])%MOD;
        }
        long long ha=0,HA=0;
        for(ri i=p[ii].s.length()-1,j=0;i>=0;i--,j++)
        {
            ha=(ha+p[ii].s[i]*po[j]%mod)%mod;
            HA=(HA+p[ii].s[i]*PO[j]%MOD)%MOD;
            if(mp.count((ha-val[i]+mod)%mod*inv[i]%mod)&&MP.count((HA-VAL[i]+MOD)%MOD*INV[i]%MOD))
            ans+=min(mp[(ha-val[i]+mod)%mod*inv[i]%mod],MP[(HA-VAL[i]+MOD)%MOD*INV[i]%MOD]); 
        }
        mp[ha]++,MP[HA]++;
    }
    cout<<ans;
    
    
} 
View Code

 

posted @ 2022-05-05 19:56  VxiaohuanV  阅读(41)  评论(0编辑  收藏  举报