UVA 11732 "strcmp()" Anyone?

来源:互联网 发布:eve捏脸数据男 编辑:程序博客网 时间:2024/05/22 03:28

题意: 输入n个字符串,两两调用一次strcmp(),问字符比较的总次数。

分析:两个相同字符         比较2次

           两个不同字符         比较1次

           ‘\0’和'\0‘                  比较两次

            '\0'和其它字符       比较一次

思路: 建一颗字典树,然后每insert一个字符串,就计算该字符串要与前面加入的字符串共比较多少次,这样就能得到最后的答案。

但是这个题有个坑点,节点太多,在最坏的情况下有4000*1000个节点,每个节点56个不同的字符,那么明显会MLE的,而且这

样也会TLE的。所以要使用压缩算法(左兄弟,右孩子字典树)。建树的方式可以看下图,一看应该就明白了。


代码如下:

#include<stdio.h>#include<math.h>#include<string.h>#include<string>#include<iostream>#include<algorithm>#include<queue>#include<map>using namespace std;#define ll long long #define nn 4000100int head[nn];   //第i个结点的左儿子编号int son[nn];//第i个结点的右兄弟编号char ch[nn];    //第i个结点上的字符int tot[nn];//第i个结点为根的子树包含的叶结点总数int sz;ll ans;struct Trie{void init(){sz = 1;ans = 0;ch[0] = tot[0] = head[0] = son[0] = 0;}void insert(char *s){int u = 0,v;int n = strlen(s);for (int i = 0; i <= n; i++){for (v = head[u]; v; v = son[v])if (ch[v] == s[i])break;if (!v){v = sz++;tot[v] = 0;ch[v] = s[i];son[v] = head[u];head[u] = v;head[v] = 0;}ans += (ll)(tot[u] - tot[v])*(2 * i + 1);if (n == i){ans +=(ll) tot[v] * (2 * i + 2);tot[v]++;}tot[u]++;u = v;}}};char str[4010];int main(){int tt = 1,n;while (scanf("%d", &n) &&n){Trie t;t.init();for (int i = 0; i < n; i++){scanf("%s", str);t.insert(str);}printf("Case %d: %lld\n", tt++, ans);}return 0;}

0 0