UVA_11732_“strcmp()” Anyone?
o(︶︿︶)o 唉,菜鸟整理出来大神的代码~
附加个前向星式建图
/* 题意: 给出n个字符串, 计算两两比较的次数. 每次比较都需要比较(str1[i] == str2[i])和 (str1[i] == '\0'各一次). 点评: 将N个字符串插入前缀树,‘\0’也插入,这样就能区分字符串的终结点 S1与S2的共同前缀S,则比较次数为len(S)*2+1 但S1与S2相同,则比较次数为 (len(S1)+1)*2 (注意:这时连'\0’都算进去了噢~,因为适用性,所以模板最好是用一维的前向星式的 */ #include <cstdio> #include <iostream> #include <cstring> using namespace std; #define MAX 1005 const int maxnode = 4001*1000+5; const int sigma_size = 26; typedef long long ll; struct Trie { int first[maxnode], next[maxnode]; //前向星式子建图还记得么,亲? int total[maxnode], ch[maxnode]; //total[i]记录每个节点被遍历的的次数,ch[i]记录字符串的值的 int sz; //记录ch的坐标的 void clear() { sz = 1; total[0] = first[0] = next[0] = 0; } void insert(const char *s) { int u = 0, v, n = strlen(s); total[u]++; for(int i = 0; i <= n; ++i) { bool flag = false; for(v = first[u]; v != 0; v = next[v]) //前向星式遍历 { if(ch[v] == s[i]) { flag = true; break; } } if( !flag ) { v = sz++; total[v] = 0; //初始化 ch[v] = s[i]; next[v] = first[u]; first[u] = v; first[v] = 0; } u = v; total[u]++; } } void dfs(int depth, int u, ll &ans) { if( first[u] == 0 ) ans += total[u]*(total[u]-1)*depth; //如果下面没有节点了,那么ans*=total[u]*(total[u]-1)*depth else { int sum = 0; for(int v = first[u]; v != 0; v = next[v]) sum += total[v]*(total[u]-total[v]); //否则计算比较次数,当前节点-相同的分支的节点的数量 ans += (sum/2*(2*depth+1)); for(int v = first[u]; v != 0; v = next[v]) dfs(depth+1, v, ans); } } }; int n; char str[MAX]; Trie tr; int main() { int t = 1; while(~scanf("%d", &n)) { if(n == 0) break; tr.clear(); for(int i = 0; i < n; ++i) { scanf("%s", str); tr.insert(str); } ll ans = 0; tr.dfs(0, 0, ans); printf("Case %d: %lld\n", t++, ans); } return 0; }