UVA 11732 "strcmp()" Anyone? (Trie)

题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2832


题意:模拟strcmp()函数,给n个字符串,两两之间进行比较,问需要进行多少次比较?

解析:字符串很多,数据量大,按题意两两比较显然不现实。如果把所有的单词插入到一棵Trie里面会怎么样呢?考虑than和that对应的结点,than和that的前3个字符是一样的,但第4个字符不同,因此比较次数是7。不仅如此,任何两个在同一结点处分叉的字符串都需要比较7次。



AC代码:

#include <bits/stdc++.h>
using namespace std;

const int maxnode = 4000 * 1000 + 5;
const int sigma_size = 26;

struct Trie{    //由于字符集较大,故用左儿子-右兄弟表示法保存
    int head[maxnode];   //左儿子编号
    int next[maxnode];   //右兄弟编号
    char ch[maxnode];    //结点上的字符
    int tot[maxnode];    //以该结点为根的结点总数
    int sz;
    long long ans;

    void clear(){ sz = 1; tot[0] = head[0] = next[0] = 0; }  //初始只有一个根结点

    void insert(const char *s){
        int u = 0, v, n = strlen(s);
        tot[0] ++;
        for(int i=0; i<=n; i++){
            bool found = false;
            for(v=head[u]; v!=0; v=next[v]){
                if(ch[v] == s[i]){
                    found = true;
                    break;
                }
            }
            if(!found){   //没找到,新建节点
                v = sz++;
                tot[v] = 0;
                ch[v] = s[i];
                next[v] = head[u];
                head[u] = v;   //插到链表首部
                head[v] = 0;
            }
            u = v;
            tot[u] ++;
        }
    }

    // 统计LCP=u的所有单词两两的比较次数之和
    void dfs(int depth, int u) {
        if(head[u] == 0) // 叶结点
          ans += tot[u] * (tot[u] - 1) * depth;
        else {
          int sum = 0;
          for(int v = head[u]; v != 0; v = next[v])
            sum += tot[v] * (tot[u] - tot[v]); // 子树v中选一个串,其他子树中再选一个
          ans += sum / 2 * (2 * depth + 1);    // 每种选法统计了两次,故除2
          for(int v = head[u]; v != 0; v = next[v])
            dfs(depth+1, v);
        }
    }

    // 统计
    long long count() {
        ans = 0;
        dfs(0, 0);
        return ans;
    }

};

Trie T;

int main(){
    #ifdef sxk
        freopen("in.txt", "r", stdin);
    #endif // sxk

    int n, t = 0;
    char s[1002];
    while(scanf("%d", &n) != EOF && n){
        T.clear();
        for(int i=0; i<n; i++){
            scanf("%s", s);
            T.insert(s);
        }
        printf("Case %d: %lld\n", ++t, T.count());
    }
    return 0;
}




是的,C++中确实有`strcmp`函数。`strcmp`是一个字符串比较函数,用于比较两个字符串是否相等。它是在C++标准库中的`<cstring>`(在C++11及以后的版本中,这个库通常被重命名为`<string>`)中定义的。 函数的原型通常如下: ```cpp int strcmp(const char *str1, const char *str2); ``` 这个函数会返回一个整数,如果`str1`和`str2`完全相同,它会返回0。如果`str1`在字典序上小于`str2`,它会返回一个负数。如果`str1`在字典序上大于`str2`,它会返回一个正数。 使用这个函数时,需要注意以下几点: * 字符串必须以空字符('\0')结尾,否则可能会产生未定义的行为。 * 字符串必须以空字符结尾的相同方式进行比较。否则可能会得到错误的结果。 * 两个字符串的指针参数不能是NULL,否则会抛出运行时错误。 使用这个函数的一个例子可能是这样的: ```cpp #include <cstring> #include <iostream> int main() { std::string str1 = "Hello"; std::string str2 = "Hello"; int result = strcmp(str1.c_str(), str2.c_str()); if (result == 0) { std::cout << "Strings are equal." << std::endl; } else if (result < 0) { std::cout << "String1 is less than String2." << std::endl; } else { std::cout << "String1 is greater than String2." << std::endl; } return 0; } ``` 这个程序将打印出 "Strings are equal.",因为两个字符串是相同的。请注意,为了安全起见,最好始终使用字符串的`.c_str()`方法来获取C风格的字符串,以便在需要使用`strcmp`或类似函数的情况下使用它们。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值