给定
这一题可以说确实很高妙,确实没想到还可以这么处理。
第一眼以为是一些类似 期望DP 的东西,然后想了半天也没想到什么复杂度正确的做法,实际上这道题是从期望的意义去找性质。
首先我们考虑对于一个串
而若存在
对于其它的情况,显然会由
然后对于求前缀,显然可以通过 Trie树 解决,同时也可以考虑一些更简单的方法:
开一个 unordered_set,往里面丢每个串的哈希值,然后对于每个串的每个前缀的哈希在里面查一下然后记录即可,最终复杂度
xxxxxxxxxx79123
45678910
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
222324
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 初稿