您的位置:首页 > 其它

HDU 3724 Encoded Barcodes (2010 Asia Tianjin Regional Contest )

2015-11-06 21:53 423 查看
【题目链接】http://acm.hdu.edu.cn/showproblem.php?pid=3724

【解题报告】

trie树基础题。建立静态trie树,然后查找即可。有两个要点。

1.如何确定某个前缀覆盖了多少个单词。
很简单,我们每插入一个单词的时候,在它走过的路径上所有结点权值加1,即表示当前结点被覆盖过多少次。那么我们查找前缀的时候,前缀的最后一个字母落在哪一个节点上,返回该点权值即可。

2.如何把一个barcode转化为二进制数。
对于读入的8个数,找到最大数max_num,那么和他一样在二进制数位中表示为1的那些数A[i],满足这样一个关系:fabs(max_num-A[i])/max_num<0.1.(注意为了防止某些坑点,最好加上一个eps精度控制)


这道题目我MLE&RE了十几发。开始我不加思考的算出最多会有30*1e5个节点,所以数组直接开超内存了(根据trie树的特点,一定会有大量单词覆盖相同节点,如果不是特意卡内存显然不需要开这么大…),改完之后提交又RE,误以为是空间开小了然后就纠结…最后发现,因为我在进行prefix查找的时候,是一边读入prefix一边遍历trie树,当trie树不存在这样一个prefix的时候,直接return 0,这样导致可能还有部分数据没有读入,于是就RE了….查这个错误查了好久好久,如果不犯懒老老实实写几组数据测一测应该可以避免这样额外的时间开支。

【参考代码】

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int eps=1e-6;
const int maxnode=2*1e5+50;
const int bit[9]={0,128,64,32,16,8,4,2,1 };
int barcode[9];

struct TRIE{
int ch[maxnode][26];
int val[maxnode];
int sz;
void clr(){  sz=1; memset(ch,0,sizeof(ch)); memset(val,0,sizeof(val)); }
int idx(char c ){ return c-'a'; }
int read()
{
float num[9];
float max_num=0;
for( int j=1; j<=8; j++ )
{
scanf("%f",&num[j]);
if(num[j]-max_num>eps)max_num=num[j];
}
for( int j=1; j<=8; j++ )
{
if( fabs(num[j]-max_num)/max_num-0.1<eps )barcode[j]=1;
else barcode[j]=0;
}
int c=0;
for( int j=1; j<=8; j++ )c+=barcode[j]*bit[j];
return c;
}

void ins( char* S )
{
int u=0,L=strlen(S);
for( int i=0; i<L; i++ )
{
int c=idx(S[i]);
if( !ch[u][c] )
{
ch[u][c]=sz++;
}
val[ch[u][c]]++;
u=ch[u][c];
}
}

int find_pre( int K )
{
int u=0;
bool ok=true;
for( int i=1; i<=K; i++ )
{
int c=read()-97;
if(!ch[u][c]) ok=false;
u=ch[u][c];
}
if(ok)return val[u];
else return 0;
}

}trie;

int main()
{
int N,M,K;
while(~scanf( "%d%d",&N,&M ))
{
trie.clr();
int ans=0;
for( int i=1; i<=N; i++ )
{
char name[40];
scanf("%s",name);
trie.ins( name );
}
for( int i=1; i<=M; i++ )
{
scanf("%d",&K );
ans+=trie.find_pre( K );
}
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: