给定
这一题可以说确实很高妙,确实没想到还可以这么处理。
第一眼以为是一些类似 期望DP 的东西,然后想了半天也没想到什么复杂度正确的做法,实际上这道题是从期望的意义去找性质。
首先我们考虑对于一个串
而若存在
对于其它的情况,显然会由
然后对于求前缀,显然可以通过 Trie树 解决,同时也可以考虑一些更简单的方法:
开一个 unordered_set
,往里面丢每个串的哈希值,然后对于每个串的每个前缀的哈希在里面查一下然后记录即可,最终复杂度
xxxxxxxxxx
791
2
3
4
5
6
7
8
9
10
11using namespace std;
12
13mt19937 rnd(random_device{}());
14int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
15bool rnddd(int x){return rndd(1, 100) <= x;}
16
17typedef unsigned int uint;
18typedef unsigned long long unll;
19typedef long long ll;
20typedef long double ld;
21
22
23
24
25template < typename T = int >
26inline T read(void);
27
28int N;
29int cntx[510000], cnty[510000];
30ll inv_2;
31string S[510000];
32unordered_map < unll, int > idx;
33
34ll qpow(ll a, ll b){
35 ll ret(1), mul(a);
36 while(b){
37 if(b & 1)ret = ret * mul % MOD;
38 b >>= 1;
39 mul = mul * mul % MOD;
40 }return ret;
41}
42
43int main(){
44 inv_2 = qpow(2, MOD - 2);
45 N = read();
46 for(int i = 1; i <= N; ++i){
47 cin >> S[i];
48 unll cur(0);
49 for(auto c : S[i])(cur *= BASE) += c;
50 idx.insert({cur, i});
51 }
52 for(int i = 1; i <= N; ++i){
53 unll cur(0);
54 for(auto c : S[i]){
55 (cur *= BASE) += c;
56 if(idx.find(cur) != idx.end())++cntx[i], ++cnty[idx[cur]];
57 }cntx[i]--, cnty[i]--;
58 }
59 for(int i = 1; i <= N; ++i)
60 printf("%lld\n", (cntx[i] + (N - cntx[i] - cnty[i] - 1) * inv_2 % MOD + 1) % MOD);
61 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
62 return 0;
63}
64
65template < typename T >
66inline T read(void){
67 T ret(0);
68 int flag(1);
69 char c = getchar();
70 while(c != '-' && !isdigit(c))c = getchar();
71 if(c == '-')flag = -1, c = getchar();
72 while(isdigit(c)){
73 ret *= 10;
74 ret += int(c - '0');
75 c = getchar();
76 }
77 ret *= flag;
78 return ret;
79}
update-2023_01_18 初稿