CF1902E题解

思路

通过观察,我们不难得到,这个 C 函数的值,即为两个字符串的长度之和,减去第一个字符串的后缀与第二个字符串的前缀最长重合部分的长度(注意 C 是个递归函数)。
那么不难想到,我们可以用一个 Trie 来存贮每个字符串,并且用一个 cnt 数组来存储每个节点被经过的次数。操作完成之后,我们可以将每一个字符串翻转之后在这个 Trie 中查询,那么这个字符串的长度乘以 2,再减去经过节点的 cnt 之和,就是这个字符串作为第一个字符串的 C 函数值之和。

代码

#include <bits/stdc++.h>
#define PII pair<int, int>
#define PLL pair<ll, ll>
#define lowbit(x) x & (-x)
#define fs(x) fixed << setprecision(x)
using namespace std;
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
#define int long long

const int maxn = 1e6 + 5;

int n, trie[maxn][26], cnt[maxn], idx, sum;
vector<string> word;

inline void insert(string w){
    int p = 0, len = w.length();
    for (int i = 0; i < len; i++){
        int c = w[i] - 'a';
        if (!trie[p][c])
            trie[p][c] = ++idx;
        p = trie[p][c];
        ++cnt[p];
    }
    return ;
}

inline int query(string w){
    int p = 0, len = w.length(), res = sum + len * n;
    for (int i = len - 1; i >= 0; i--){
        int c = w[i] - 'a';
        if (!trie[p][c])
            return res;
        p = trie[p][c];
        res -= 2 * cnt[p];
    }
    return res;
}

signed main(){
    cin >> n;
    for (int i = 1; i <= n; i++){
        string a;
        cin >> a;
        word.push_back(a);
        sum += a.length();
        insert(a);
    }
    int ans = 0;
    for (int i = 0; i < n; i++){
        ans += query(word[i]);
    }
    cout << ans << '\n';
    return 0;
}
posted @   Floze3  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示