给你n个单词,让他们两两比较,要求他们运用strcmp时,进行比较的次数。
边建树边统计
#include <iostream> #include <cstdio> #include <sstream> #include <cstring> #include <map> #include <set> #include <vector> #include <stack> #include <queue> #include <algorithm> #include <cmath> #define rap(i, a, n) for(int i=a; i<=n; i++) #define rep(i, a, n) for(int i=a; i<n; i++) #define lap(i, a, n) for(int i=n; i>=a; i--) #define lep(i, a, n) for(int i=n; i>a; i--) #define MOD 2018 #define LL long long #define ULL unsigned long long #define Pair pair<int, int> #define mem(a, b) memset(a, b, sizeof(a)) #define _ ios_base::sync_with_stdio(0),cin.tie(0) //freopen("1.txt", "r", stdin); using namespace std; const int maxn = 4000005, INF = 0x7fffffff; int trie[maxn][62], sum[maxn], isend[maxn]; string str; int rt, tot; LL ans; int idx(char s){ if(s >= '0' && s <= '9'){ return s - '0'; } else if(s >= 'A' && s <= 'Z'){ return 10 + s - 'A'; } else{ return 36 + s - 'a'; } } void build() { int len = str.size(); rt = 0; for(int i=0; i<len; i++) { int x = idx(str[i]); if(trie[rt][x] == 0) { ans += sum[rt] * (2 * i + 1); //如果不存在这个字母 则与这个字母前的所有前缀都不同 trie[rt][x] = ++tot; } else ans += (sum[rt] - sum[trie[rt][x]]) * (2 * i + 1); //如果存在这个字母 则只与在这个位置上和这个字母不相同的 不同 sum[rt]++; //这种写法是从祖结点开始算的 可以返回不同单词的个数 即sum[0] rt = trie[rt][x]; } ans += isend[rt] * 2 * (len + 1); //因为有 所以是len+1 ans += (sum[rt] - isend[rt]) * (2 * len + 1); sum[rt]++; isend[rt]++; } void init() { tot = ans = 0; mem(isend, 0); mem(sum, 0); mem(trie, 0); } int main() { int n, kase = 0; while(~scanf("%d", &n) && n) { init(); rap(i, 1, n) { cin>> str; build(); } printf("Case %d: ", ++kase); cout<< ans <<endl; } return 0; }