5.12 每日一题题解

P4421 [COCI2017-2018#1] Lozinke

涉及知识点:

  • hash/stl

solution:

  • (本题将每一个字符串的每一个子串的哈希值扔到map里)
  • (因为本题的字符串长度小,所以也可以直接存子串)
  • (注意本题每个字符串如果有重复的子串,只取一个,这里是用set去重)
  • (然后看每个字符串对应的键值为多少相加即可(注意要减去它自己))
  • (本题由于字符串数目过多,且不用排序,最好使用unordered_map)

std:

#include <bits/stdc++.h>

using namespace std;

typedef unsigned long long ull;

const int P = 131;
char str[15];
ull h[15],p[15];
ull sub[20010];

unordered_map<ull,int> mp;
set<ull> se;

ull get(int l,int r)
{
    return h[r] - h[l-1] * p[r-l+1];
}

int main()
{
    int n;
    scanf("%d",&n);
    p[0]=1;
    for (int t = 1 ; t <= n ; t ++ )
    {
        se.clear();
        scanf("%s",str+1);
        int len = strlen(str+1);
        for (int i = 1 ; i <= len; i ++ )
        {
            if(!p[i]) p[i] = p[i-1] * P;
            h[i] = h[i-1]*P + (str[i]-'a'+1);
        }
        sub[t] = h[len];
        for (int l = 1 ; l <= len ; l ++ )
        {
            for (int r = l ; r <= len; r ++ )
            {
                se.insert(get(l,r));
            }
        }
        for (set<ull>::iterator it = se.begin() ; it != se.end() ; it ++ )
        {
            mp[*it] ++ ;
        }
    }
    ull ans = 0;
    for (int i = 1 ; i <= n ; i ++ )
    {
        auto it = mp.find(sub[i]);
        if(it == mp.end()) continue;
        else ans += it->second-1;
    }
    printf("%lld
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/QFNU-ACM/p/12876556.html