[BZOJ4084][SDOI2015]双旋转字符串(hash)

本文介绍了一种高效的字符串匹配算法,通过哈希技术实现快速查找。利用map记录短串哈希值出现频次,对长串进行枚举匹配,优化取模操作提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:

我是超链接

题解:

假设S是长度较长的集合。
将T中的串哈希,用map记录每个哈希值出现了多少次。
然后枚举S串,在map中找可以拼接的T串的个数。
串S由abc->cab是O(1)的
不要那么多次取模。

代码:

#include <map>
#include <string>
#include <cstdio>
#include <cstring>
#include <iostream>
#define LL long long
using namespace std;
const int N=4000005;
const int base=131;
const LL mod=998244353; 
string s[N],t[N];LL mi[N];
map<LL,int>mp;
LL ksm(LL a,LL k)
{
    LL ans=1;
    for (;k;k>>=1,a=a*a%mod)
      if (k&1) ans=ans*a%mod;
    return ans;
}
int main()
{
    int ts,tt,n,m;
    scanf("%d%d%d%d",&ts,&tt,&n,&m);
    if (n<m)
    {
        swap(ts,tt);swap(n,m);
        for (int i=1;i<=tt;i++) cin>>t[i];
        for (int i=1;i<=ts;i++) cin>>s[i];
    }
    else
    {
        for (int i=1;i<=ts;i++) cin>>s[i];
        for (int i=1;i<=tt;i++) cin>>t[i];
    }
    //t是短的 
    int len=(n+m)/2;
    for (int i=1;i<=tt;i++)
    {
        LL hs=0;
        for (int j=0;j<m;j++) hs=(hs*base%mod+t[i][j])%mod;
        mp[hs]++;
    }
    mi[0]=1;for (int i=1;i<=len;i++) mi[i]=mi[i-1]*base%mod;
    LL ans=0;
    LL inv=ksm(base,mod-2);
    for (int i=1;i<=ts;i++)
    {
        LL qz=0,now=0;
        for (int j=len;j<n;j++) qz=(s[i][j]*mi[len*2-j-1]+qz)%mod;
        for (int j=0;j<len;j++) now=(now*base%mod+s[i][j])%mod;
        for (int j=0;j<len;j++)
        {
            ans+=mp[(now-qz+mod)%mod];
            now=((now-s[i][len-j-1]+mod)*inv%mod+s[i][len-j-1]*mi[len-1])%mod;
        }
    }
    printf("%lld",ans);
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值