zoukankan      html  css  js  c++  java
  • A All with Pairs (哈希值+next)

    题:https://ac.nowcoder.com/acm/contest/5667/A

    题意:给定n个串,主要求每个串和n个中的每一个串的最大相同公共前后缀的长度,然后计算题目给式子

    分析:对于n个串的后缀,我们考虑用哈希值来代表,最多共有1e6个值(sum(|si|)),预处理这部分,用map记录哈希值出现的个数;

       然后简单点考虑就枚举前缀,直接算当前前置的哈希值在之前预处理的后缀中出现了多少次;

       但会造成“重复”的现象,比如枚举的前缀的前缀在后缀中还有贡献,这无疑是会重复算的,而我们只要最大,这些“前缀的前缀”不能算进答案里面;

       所以我们考虑可以用kmp的next数组,next数组的含义即 i 位匹配错了要跳转去哪个位置,所以大前缀的贡献为num[i], 则相应的大前缀的前缀要减去这部分贡献,即num[next[i]]-num[i];

    #include<bits/stdc++.h>
    using namespace std;
    #define pb push_back
    #define MP make_pair
    typedef long long ll;
    typedef unsigned long long ull;
    const int mod=998244353;
    const int M=1e6+6;
    const int N=1e5+5;
    const int inf=0x3f3f3f3f;
    const ll INF=1e18;
    const ull base=217;
    unordered_map<ull,int>mp;
    vector<ull>a[N];
    vector<int>nex[N];
    ull jinzhi[M];
    ll num[M];
    char s[M];
    void getnext(int id){
    
        int m=strlen(s+1);
        int j=0;
        nex[id].resize(m+1);
        for(int i=2;i<=m;i++){
            while(j&&s[i]!=s[j+1])
                j=nex[id][j];
            if(s[i]==s[j+1])
                j++;
            nex[id][i]=j;
        }
    }
    int main(){
        jinzhi[0]=1;
        for(int i=1;i<M;i++)
            jinzhi[i]=jinzhi[i-1]*base;
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%s",s+1);
            int len=strlen(s+1);
            a[i].resize(len+1);
            a[i][0]=0;
            for(int j=1;j<=len;j++)
                a[i][j]=a[i][j-1]*base+(s[j]-'a'+1);
    
            for(int j=0;j<len;j++){
                ull tmp=a[i][len]-a[i][j]*jinzhi[len-j];
                mp[tmp]++;
            }
            getnext(i);
        }
        ll ans=0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<nex[i].size();j++){
                num[j]=mp[a[i][j]];
                num[nex[i][j]]-=num[j];
            }
            for(int j=1;j<nex[i].size();j++){
                ans=(1ll*num[j]*j%mod*j%mod+ans)%mod;
            }
            ///cout<<ans<<endl;
        }
        printf("%lld
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    Python之面向对象新式类和经典类
    Python之面向对象继承和派生
    Python之面向对象类和对象
    Python之面向对象的程序设计
    Python之面向对象函数式编程
    Python之内置函数
    列表解析与生成器表达式
    03: 交换机基本原理与配置
    02: 网络布线与数制转换
    01:数据封装解封的过程
  • 原文地址:https://www.cnblogs.com/starve/p/13303326.html
Copyright © 2011-2022 走看看