标签:
称号:给你一些话,给你一个字符串比较函数,所有的话都当奇偶校验,什么是比较次数。
分析:弦、特里。
首先。看数据大小,假设正常的发现线索,会议TLE和MLE。
由于,常规的字典树深度为1000,并且有可能会有大量的指正空间浪费。
所以,採用树的压缩算法(左兄弟,右孩子)。能够提高执行效率。
然后。在字典树上同级就可以。统计时,能够先建树再统计,或者边建树边统计。
这里我选用边建树边统计的方法(网上大量的做法,都是先建树再统计的,搜索求解)
每次插入单词时。它仅仅与前面插入的单词比較;单词的比較次数为当中每一个字母的比較次数的和。
单词中每一个字母的比較次数。就是这个字母的根节点包括的单词个数。
单词比較函数例如以下:
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]; }由于比較函数如上,计算时要注意下面几点:
1.同样长度为L的两个单词比較代价为2L-1。出最后一次外要进行s结束的推断;
2.单词的比較长度应该为strlen(str)+1,结束符也是比較的一环;
3.假设两个单词同样,则多计算一次结束推断。比較次数+1。
注意:使用LL,否则数据会溢出。
#include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> using namespace std; typedef long long LL; char words[1010]; /* Trie define */ #define nodesize 4444444 //节点个数 typedef struct node1 { char value; int size; int count; node1* Lchild; node1* Rchild; }tnode; tnode dict[nodesize]; class Trie { private: LL count; int size; tnode* root; public: Trie() {initial();} void initial() { memset( dict, 0, sizeof(dict) ); size=0;count=0LL;root=newnode(0); } tnode* newnode( char c ) { dict[size].value = c; return &dict[size ++]; } void insert( char* word, int L ) { tnode* now = root->Rchild,*save = root; int same = 1; for ( int i = 0 ; i <= L ; ++ i ) { if ( !now ) { save->Rchild = newnode(word[i]); now = save->Rchild; now->count = 1; same = 0; }else { if ( i ) count += now->count; count += now->count ++; while ( now->Lchild && now->value != word[i] ) now = now->Lchild; if ( now->value != word[i] ) { now->Lchild = newnode(word[i]); now = now->Lchild; same = 0; } } save = now; now = save->Rchild; } if ( same ) save->size ++; count += save->size; } LL query() {return count;} }trie; /* Trie end */ int main() { int Case = 1,N; while ( scanf("%d",&N) != EOF ) { if ( !N ) break; trie.initial(); for ( int i = 0 ; i < N ; ++ i ) { scanf("%s",words); trie.insert(words,strlen(words)); } printf("Case %d: %lld\n",Case ++,trie.query()); } return 0; }
版权声明:本文博主原创文章。博客,未经同意不得转载。
标签:
原文地址:http://www.cnblogs.com/yxwkf/p/4821897.html