UVA 11732("strcmp()" Anyone?-Trie与左兄弟右儿子)

“strcmp()” Anyone?

strcmp() is a library function in C/C++ which compares two strings. It takes two strings as input parameter and decides which one is lexicographically larger or smaller: If the first string is greater then it
returns a positive value, if the second string is greater it returns a negative value and if two strings are equal it returns a zero. The code that is used to compare two strings in C/C++ library is shown below:


int strcmp(char *s, char *t)

{

int i;

for (i=0; s[i]==t[i]; i++)

if (s[i]==‘\0‘)

return 0;

return s[i] - t[i];

}


Figure: The standard strcmp() code provided for this problem.

The number of comparisons required to compare two strings in strcmp() function is never returned by the function. But for this problem you will have to do just that at a larger scale. strcmp() function continues
to compare characters in the same position of the two strings until two different characters are found or both strings come to an end. Of course it assumes that last character of a string is a null (‘\0’) character. For example the table below shows what happens
when “than” and “that”; “therE” and “the” are compared using strcmp() function. To understand how 7 comparisons are needed in both cases please consult the code block given above.


t


h


a


N


\0


 


t


h


e


r


E


\0


 


=


=


=



 


=


=


=



 


 


t


h


a


T


\0


t


h


e


\0


 


 


Returns negative value

7 Comparisons


Returns positive value

7 Comparisons

Input

The input file contains maximum 10 sets of inputs. The description of each set is given below:

Each set starts with an integer N (0

Input is terminated by a line containing a single zero. Input file size is around 23 MB.

Output

For each set of input produce one line of output. This line contains the serial of output followed by an integer T. This T denotes the total number of comparisons that are required in the strcmp() function if
all the strings are compared with one another exactly once. So for N strings the function strcmp() will be called exactly N(N-1)/2 times. You have to calculate total number of comparisons inside
the strcmp() function in those N(N-1)/2 calls. You can assume that the value of T will fit safely in a 64-bit signed integer. Please note that the most straightforward solution (Worst Case Complexity
O(N2 *1000)) will time out for this problem.

Sample Input

2

a

b

4

cat

hat

mat

sir

0

Output for Sample Input

Case 1: 1

Case 2: 6

Trie dp显然,问题是4000000个点62个Sigma会MLE

于是我们用边表存边,类似【左兄弟右儿子】的做法存边

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<functional>
#include<iostream>
#include<cmath>
#include<cctype>
#include<ctime>
using namespace std;
#define For(i,n) for(int i=1;i<=n;i++)
#define Fork(i,k,n) for(int i=k;i<=n;i++)
#define Rep(i,n) for(int i=0;i<n;i++)
#define ForD(i,n) for(int i=n;i;i--)
#define RepD(i,n) for(int i=n;i>=0;i--)
#define Forp(x) for(int p=pre[x];p;p=next[p])
#define Forpiter(x) for(int &p=iter[x];p;p=next[p])
#define Lson (x<<1)
#define Rson ((x<<1)+1)
#define MEM(a) memset(a,0,sizeof(a));
#define MEMI(a) memset(a,127,sizeof(a));
#define MEMi(a) memset(a,128,sizeof(a));
#define INF (2139062143)
#define F (20071027)
#define MAXT (10+10)
#define MAXN (4001+100)
#define Sigma_size (26*2+10)
#define MAXLen (1000+10)
#define MINLen (1)
#define MAXNode (4000000+10)
#define MAXM (MAXNode)
long long mul(long long a,long long b){return (a*b)%F;}
long long add(long long a,long long b){return (a+b)%F;}
long long sub(long long a,long long b){return (a-b+(a-b)/F*F+F)%F;}
typedef long long ll;
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int tt=0;
class Trie
{
public:
//	int ch[MAXNode][Sigma_size];
	int pre[MAXNode],edge[MAXM],next[MAXM],pathc[MAXM],Size;
	int v[MAXNode],f[MAXNode],siz;
	Trie(int _siz=0):siz(_siz),Size(0){MEM(pre) MEM(edge) MEM(next) MEM(v) MEM(f)}
	void mem(int _siz=0){Size=0;siz=_siz; MEM(pre) MEM(edge) MEM(next) MEM(v) MEM(f)	}
	int idx(char c)
	{
		if ('0'<=c&&c<='9') return c-'0';
		if ('a'<=c&&c<='z') return c-'a'+10;
		if ('A'<=c&&c<='Z') return c-'A'+36;
	}
	void insert(char *s)
	{
		int u=0,n=strlen(s);
		Rep(i,n)
		{
			int c=idx(s[i]);
			bool flag=0;
			Forp(u)
			{
				if (pathc[p]==c)
				{
					u=edge[p];
					flag=1; break;
				}
			}
			if (!flag)
			{
				edge[++Size]=++siz;
				pathc[Size]=c;
				next[Size]=pre[u];
				pre[u]=Size;
				u=siz;
			}
		}
		v[u]++;
	}
	void make_f(int u)
	{
		f[u]=v[u];
		Forp(u)
		{
			make_f(edge[p]);
			f[u]+=f[edge[p]];
		}
//		cout<<u<<' '<<f[u]<<' '<<v[u]<<endl;
	}
	ll dfs(int u)
	{
		ll ans=0,node_sum=v[u];
		if (v[u]) ans+=v[u]*(v[u]-1)/2*2;
		Forp(u)
		{
			int V=edge[p];
			if (V)
			{
				ans+=f[V]*(f[V]-1)/2*2;
				ans+=node_sum*f[V];
				ans+=dfs(V);
				node_sum+=f[V];
			}
		}
		return ans;
	}
}T;
int n;
char s[MAXLen];
int main()
{
//	freopen("uva11732.in","r",stdin);
//	freopen(".out","w",stdout);
	while(scanf("%d",&n)==1&&n)
	{
		T.mem();
		For(i,n)
		{
			scanf("%s",s);
			T.insert(s);
		}
		T.make_f(0);
		ll ans=T.dfs(0);
		printf("Case %d: %lld\n",++tt,ans);
	}
	return 0;
}
时间: 2024-09-30 10:21:50

UVA 11732("strcmp()" Anyone?-Trie与左兄弟右儿子)的相关文章

UVA - 11732 &quot;strcmp()&quot; Anyone?左兄弟右儿子trie

input n 2<=n<=4000 s1 s2 ... sn 1<=len(si)<=1000 output 输出用strcmp()两两比较si,sj(i!=j)要比较的次数,结果在long long范围内(相同字符比较两次,不相同字符比较一次,包括'\0') 做法:由于字符集太大,要用左兄弟右儿子的trie保存字符,不用每次都开ch[62]个孩子 1 #include <cstdio> 2 #include <queue> 3 #include <

UVA 11732 - strcmp() Anyone?(Trie)

UVA 11732 - strcmp() Anyone? 题目链接 题意:给定一些字符串,要求两两比较,需要比较的总次数(注意,如果一个字符相同,实际上要还要和'\0'比一次,相当比2次) 思路:建Trie树,每次建树过程中,后继后继结点就是相同结点需要比较两次ans + val * 2,否则就是不同结点ans + val,建完树就计算完了 代码: #include <cstdio> #include <cstring> const int N = 1005; const int

左儿子右兄弟Trie UVA 11732 strcmp() Anyone?

UVA 11732 strcmp() Anyone?(左儿子右兄弟Trie) ACM 题目地址: UVA 11732 strcmp() Anyone? 题意: 问strcmp函数的==语句执行了几次. UVA 11732 strcmp() Anyone?(左儿子右兄弟Trie) ACM 题目地址: UVA 11732 strcmp() Anyone? 题意: 问strcmp函数的==语句执行了几次. 分析: 大白上的题目. 听说要用左儿子右兄弟的Trie,比较省空间,顺便学了下. 一边inser

UVA 11732 strcmp() Anyone?(左儿子右兄弟Trie)

UVA 11732 strcmp() Anyone?(左儿子右兄弟Trie) ACM 题目地址: UVA 11732 strcmp() Anyone? 题意: 问strcmp函数的==语句执行了几次. 分析: 大白上的题目. 听说要用左儿子右兄弟的Trie,比较省空间,顺便学了下. 开始先建树记录次数,然后再遍历统计,结果错了... 后面参考了Shoutmon巨巨的写法,一边insert一边统计. 代码: /* * Author: illuz <iilluzen[at]gmail.com> *

uva 11732 - strcmp() Anyone? 不错的Trie题

题解:http://blog.csdn.net/u013480600/article/details/23122503 我的代码一直TLE,,,看了人家的之后,觉得1.链式前向星比较好,2.*depth而不是每过一个节点就计算,这一点很好 我是基本copy别人的代码,自己加了注释,留个记号,随后重写, 这道题同样作为链式前向星的Trie的模板 #include <cstdio> #include <cstring> #include <iostream> using n

UVa - 11732 - strcmp() Anyone?

先上题目: strcmp() Anyone? Time Limit:2000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Description J ?strcmp()? Anyone? Input: Standard Input Output: Standard Output strcmp() is a library function in C/C++ which compares two stri

uva 11732 - strcmp() Anyone?(字典树)

题目链接:uva 11732 - strcmp() Anyone? 题目大意:给定n个串,然后两两之间比较,问说总共要比较多少次. 解题思路:字典树,建立出字典树,然后根据字典树的性质在节点记录有多少个字符串包含该节点.因为节点的个数比较多,所以用左孩子右兄弟的方法建立字典树. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long

UVa 11732 &quot;strcmp()&quot; Anyone? (左儿子右兄弟前缀树Trie)

题意:给定strcmp函数,输入n个字符串,让你用给定的strcmp函数判断字符比较了多少次. 析:题意不理解的可以阅读原题https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2832 字符串很多,又很长,如果按照题目的意思两两比较,肯定会TLE,所以要用前缀树(Trie)来解决,当然只是用简单的前缀树也会TLE的, 我们必须对其进行优化,看了

UVa 11732 strcmp()函数(左孩子右兄弟表示法)

1 #include<iostream> 2 #include<algorithm> 3 #include<string> 4 #include<cstring> 5 #include<vector> 6 using namespace std; 7 8 const int maxn = 4000 * 1000 + 10; 9 int n; 10 long long ans; 11 12 struct Trie 13 { 14 int head[