UVa 11732 strcmp() Anyone?

本文讨论了如何利用字典树数据结构优化字符串比较的效率,通过分析比较次数和改进字典树的存储方式,实现了从超时到高效处理大量字符串比较的任务。文章深入探讨了字典树的实现细节,包括节点存储优化和比较次数的计算方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        题意:这题先展示了一个字符串比较函数strcmp,它的工作原理是这样的,扫描两个字符串的每一位,比较是否相等,如不相等,即可得出结果,如果相等,检查当前位是否为结尾(是结尾表明两个字符串完全相同)。也就是说,两个字符串的比较次数可以这样计算,如果串相等,需比较(长度+1)*2次;否则次数为公共前缀长度*2+1。然后现在有好多字符串,问如果这些字符串两两执行该函数比较,需要比较多少次。

        思路:字典树。随手写了个数组下标代替指针的字典树版本,结果超时了。然后我在此基础上增加了一个链表,把每个节点的所有孩子串起来,还是超时。然后我分析了一下,每个串的长度为1000,有4000个串,也就是最坏的情况下有4000000个节点,每个节点有62个孩子也就是需要4000000*62的空间,不超时也会爆内存(可能因为memset超时)。最后改成了完全以链的形式存储节点的孩子,也就是插入的时候需要沿着链寻找孩子是否已经存在。

        数据结构没问题了,怎么计算比较次数呢?字典树的每一个节点都可以表示一个公共前缀,设具有这样的公共前缀的串的数量为m,那么比较到当前节点时,需要比较的次数就是m*(m-1)/2。递推一下就能算出来了。


#include <iostream>           
#include <stdio.h>           
#include <cmath>           
#include <algorithm>           
#include <iomanip>           
#include <cstdlib>           
#include <string>           
#include <memory.h>           
#include <vector>           
#include <queue>           
#include <stack>           
#include <map>         
#include <set>         
#include <ctype.h>         
#define INF 1<<30       
#define ll long long       
#define max3(a,b,c) max(a,max(b,c))       
#define MAXN 4100000
  
using namespace std;  


struct Trie{
	ll val[MAXN];//具有相同前缀的串的数量 
	ll end[MAXN];//相同串的数量 
	char ch[MAXN];
	int head[MAXN];
	int next[MAXN];
	int sz;
	
	void init(){
		sz=1; val[0]=0;
		memset(head,0,sizeof(head));
		memset(next,0,sizeof(next));
		memset(end,0,sizeof(end));
	}
	
	void insert(char* str){
		int u=0;
		int len=strlen(str);
		val[0]++;
		for(int i=0;i<len;i++){
			
			int t=head[u];
			bool find=false;
			while(t){
				if(ch[t]==str[i]){
					u=t;
					find=1;
					break;
				}
				t=next[t];
			}
			
			if( !find ){
				int v=sz++;
				next[v]=head[u];
				head[u]=v;
				
				val[v]=0;
				ch[v]=str[i];
				head[v]=0;
				u=v;
			}
			val[u]++;
		}
		end[u]++;
	}
	
	ll sear(int u){
		ll re=(val[u]-1)*val[u]/2;
		int t=head[u];
		while(t){
			if(val[t]<=1){
				t=next[t];
				continue;
			}
			re+=(val[t]-1)*val[t]/2;
			re+=(end[t]-1)*end[t]/2;//由于没有存储结束符,需要额外计算一下串相等的情况 
			re+=sear(t);
			
			t=next[t];
		}
		return re;
	}
};

char str[1010];
Trie T;

int main(){
	int n;
	int cas=0;
	while(~scanf("%d",&n)){
		if(!n)break;
		cas++;
		T.init();

		for(int i=1;i<=n;i++){
			scanf("%s",str);
			T.insert(str);
		}
		printf("Case %d: %lld\n",cas,T.sear(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、付费专栏及课程。

余额充值