ACM必做50题的解题快速查找 BSearch Hash and so on.docx
- 文档编号:6165422
- 上传时间:2023-01-04
- 格式:DOCX
- 页数:14
- 大小:19.22KB
ACM必做50题的解题快速查找 BSearch Hash and so on.docx
《ACM必做50题的解题快速查找 BSearch Hash and so on.docx》由会员分享,可在线阅读,更多相关《ACM必做50题的解题快速查找 BSearch Hash and so on.docx(14页珍藏版)》请在冰豆网上搜索。
ACM必做50题的解题快速查找BSearchHashandsoon
ACM必做50题的解题-快速查找(B-Search,Hashandsoon).txt你不能让所有人满意,因为不是所有的人都是人成功人士是—在牛B的路上,一路勃起你以为我会眼睁睁看着你去送死吗?
我会闭上眼睛的POJ2503Babelfish
题目大意很简单,就是给你字典的对应信息,然后给你查询条件要求你输出字典查询结果,如果字符串没有在字典中则输出"eh"。
恩,学到了一个新的函数bsearch(),可以进行二分查找。
先对字典使用qsort排序然后再使用bsearch()查找字符串即可。
还学到了一个输入函数sscanf(),可以从一个字符串中读取内容,格式如下
sscanf(stringstr,stringformat[,stringvar1...])
#include
#include
#include
typedefstruct
{
charen[11];
charfn[11];
}dict;
dicta[100001];
/*定义qsort比较函数*/
intq_cmp(constvoid*a,constvoid*b)
{
returnstrcmp(((dict*)a)->fn,((dict*)b)->fn);
}
/*定义bsearch比较函数*/
intb_cmp(constvoid*a,constvoid*b)
{
returnstrcmp((char*)a,((dict*)b)->fn);
}
intmain()
{
charstr[30];
inti,sign;
dict*p;
i=0;
/*查询标记记为"未开始"*/
sign=1;
/*读取字符串直到文件结束*/
while(gets(str))
{
/*遇到空行则开始排序字典*/
if(str[0]=='\0')
{
/*查询标记记为"开始"*/
sign=0;
qsort(a,i,sizeof(dict),q_cmp);
continue;
}
/*查询未开始时读取字典信息*/
if(sign)
{
/*使用sscanf从str中读取查询要求*/
sscanf(str,"%s%s",a[i].en,a[i].fn);
i++;
}
/*查询开始时进行查询*/
else
{
/*二分查找指定字符串*/
p=(dict*)bsearch(str,a,i,sizeof(dict),b_cmp);
/*找到则输出结果*/
if(p)
{
puts(p->en);
}
/*找不到输出"eh"*/
else
{
puts("eh");
}
}
}
//system("pause");
return0;
}
POJ2513ColoredSticks欧拉通路+并查集+trie树
这道题大意是:
已知有n根木棒,每个木棒有两种颜色表示两端,问:
能不能将所有的木棒连接成一条直线(连接处颜色相同)。
可以考虑无向图的欧拉通路问题:
将每种颜色看成图中的一个节点,木棒看作连接节点的边,于是判断两点:
1,每种颜色(节点)的度
2,是否为连通图
首先,每种颜色的度可以通过每条木棒的两端颜色的累积得到,问题是,每种颜色都是字符串,怎么关联每种颜色和度呢?
最容易想到的是Hash,这肯定是可行的。
例如degree[hash(red)]=5。
表示颜色为红色的度为5。
但是,既然提示用trie树来做,那么trie树的节点的数据域就可以保存每种颜色的id(相当于分配的hash值,可以通过一个全局变量自增产生),这样经过将每种颜色字符串插入到tree中以后,通过trie树的search操作就能高效的获取每种颜色对应的id,没插入一种颜色,为其产生一个id,只需要注意相同颜色插入时的处理即可。
其次,判断无向图是否连通可以使用并查集来判定:
经过n-1各union操作后,所有节点都在一个集合(树形结构表示集合的话,即所有节点的父节点(集合代表)都一样)。
由于每种颜色是由字符串来标示的,每个集合保存颜色对应的唯一id。
通过上面两个步骤的判定,就可以得出结果。
#include
#include
usingnamespacestd;
constintmax_size=500001;
chars1[11],s2[11];
intp[max_size];
intr[max_size];
intdegree[max_size];
intnum=1;
structTreeNode
{
intid;//theidofthestring
TreeNode*next[27];
TreeNode()
{
id=0;
for(inti=0;i<27;i++)
next[i]=NULL;
}
};
TreeNode*root;
voidinsert(char*s,TreeNode*root)
{
TreeNode*p=root;
inti=0;
intl=strlen(s);
for(i=0;i { if(p->next[s[i]-'a']==NULL) p->next[s[i]-'a']=newTreeNode; p=p->next[s[i]-'a']; } if(p->id==0)//firstinsert p->id=num++; } intsearch(char*s,TreeNode*root) { TreeNode*p=root; if(p==NULL) return-1; inti=0; intl=strlen(s); for(i=0;i { if(p->next[s[i]-'a']==NULL) return-1; else p=p->next[s[i]-'a']; } returnp->id; } voidmake_set(intx) { p[x]=x; r[x]=1; } intfind_set(intx) { if(p[x]! =x) p[x]=find_set(p[x]); returnp[x]; } voidunion_set(intx,inty) { if(r[x]>r[y]) p[y]=x; elseif(r[x] p[x]=y; else { r[y]++; p[x]=y; } } intmain() { root=newTreeNode; memset(p,0,sizeof(p)); memset(degree,0,sizeof(degree)); while(scanf("%s%s",s1,s2)! =EOF) { insert(s1,root); insert(s2,root); intid1=search(s1,root); intid2=search(s2,root); degree[id1]++; degree[id2]++; if(p[id1]==0) make_set(id1); if(p[id2]==0) make_set(id2); union_set(find_set(id1),find_set(id2)); } inti=0; intsum=0; //ifthenumofnodeswhosedegreeisoddaremorethan2. for(i=1;i { if(degree[i]%2! =0)sum++; if(sum>2) { cout<<"Impossible"< return0; } } //ifthegisjoint. for(i=1;i if(find_set(i)! =find_set (1)) { cout<<"Impossible"< return0; } cout<<"Possible"< } poj1035Spellchecker 开始做字符串的题目,本人觉得最头痛噶野,好鬼唔锺意处理字符串噶野。 不过唯有硬住头皮上啦。 呢条题有个奇怪噶地方,就系用STL做的话,点都系TLE,后来改翻用C语言甘样慢慢搞先过,重要用左将近1s. 注意: (1)用另一个字符数组记录字典,然后排序,用于二分查找的。 (2)先处理与被检查数组相同长度的,然后系,比距长的,最后系比距短的。 (3)数组开得足够大啦 #include #include #include usingnamespacestd; intcmp(constvoid*p,constvoid*q){ returnstrcmp((char*)p,(char*)q); } structs{ charword[20]; intlen; }str1[10005]; charstr2[10005][20],bc[20],ch[20],*p; intbcl,n; voidinput(){ inti=0; while(strcmp(gets(str1[++i].word),"#")){ str1[i].len=strlen(str1[i].word); strcpy(str2[i],str1[i].word); } n=i; qsort(str2+1,n,sizeof(str2[0]),cmp); } voidsolve(){ inti,j,k; while(strcmp(gets(bc),"#")){ bcl=strlen(bc); p=(char*)bsearch(&bc,str2+1,n,sizeof(str2[0]),cmp); if(p) cout< else{ cout< "; for(i=1;i<=n;i++){ if(str1[i].len==bcl){ intflag=0; for(j=0;j if(str1[i].word[j]! =bc[j]) flag++; } if(flag<2)cout<<""< }elseif(bcl==str1[i].len+1){ for(j=0;j strcpy(ch,bc); for(k=j;k ch[k]=ch[k+1]; //cout< if(strcmp(ch,str1[i].word)==0){ printf("%s",str1[i].word); break; } } }elseif(bcl==str1[i].len-1){ for(j=0;j strcpy(ch,str1[i].word); for(k=j;k ch[k]=ch[k+1]; //cout< if(strcmp(ch,bc)==0){ printf("%s",str1[i].word); break; } } } } cout< } } } intmain(){ input(); solve(); return0; } POJ1200CrazySearch 这个是说一段字符串有nc种字符组成问长度为n的不同的字符串有多少个 非常关键的一条信息是nc^n最多只有16000000 so我们用nc进制的HASH来做 #include #include intn,nc; charstr[20000000]; charasca[128]; inthash[16000005]; intmain() { while(scanf("%d%d\n",&n,&nc)! =EOF) { scanf("%s",str); inti=0; intj; intkey=0; while(str[i]) { if(asca[str[i]]==0)asca[str[i]]=++key; i++; if(key==nc)break; } intlen=strlen(str); intsum; intcnt=0; for(i=0;i+n-1 { sum=0; for(j=i;j<=i+n-1;j++) { sum=sum*nc+asca[str[j]]-1; } if(hash[sum]==0) { hash[sum]=1; cnt++; } } printf("%d\n",cnt); } } POJ2002hash(枚举+哈希) 简单hash,具体做法是枚举任意两个点,因为有这由两个点所构成的边属于某个正方形那么可以计算出属于该正方形的另外两个点。 如有两个点(a1,a2)和(b1,b2),那么如果点(a1+(a2-b2),a2-(a1-b1))和点(b1+(a2-b2),b2-(a1-b1))都存在则这四个点可以构成一个正方形。 同时如果点(a1-(a2-b2),a2+(a1-b1))和点(b1-(a2-b2),b2+(a1-b1))存在那么点(a1,a2),(b1,b2),(a1-(a2-b2),a2+(a1-b1))和(b1-(a2-b2),b2+(a1-b1))又可以构成一个正方形,差不多思想就是这个样子,不过好像时间比较长1500多ms,应该还可以优化。 #include usingnamespacestd; structpoint { point() { index=-1; next=NULL; } point(intindex,point*next) { this->index=index; this->next=next; } intindex; point*next; }; inta[1001][2]; boolfind(pointhash_table[],int,int); intmain() { intn,value; while(scanf("%d",&n)&&n) { longresult=0; pointhash_table[40001]; for(inte=0;e { scanf("%d%d",&a[e][0],&a[e][1]); value=a[e][0]+a[e][1]; if(value<0)value=-value; if(hash_table[value].index==-1)hash_table[value].index=e; else { point*p=&hash_table[value]; while(p->next! =NULL)p=p->next; p->next=newpoint(e,NULL); } } for(intx=0;x for(inty=x+1;y { intd_x=a[x][0]-a[y][0]; intd_y=a[x][1]-a[y][1]; if(find(hash_table,a[x][0]-d_y,a[x][1]+d_x)&& find(hash_table,a[y][0]-d_y,a[y][1]+d_x)) result++; if(find(hash_table,a[x][0]+d_y,a[x][1]-d_x)&& find(hash_table,a[y][0]+d_y,a[y][1]-d_x)) result++; } printf("%ld\n",result/4); } return0; } boolfind(pointhash_table[40001],intx,inty) { intvalue=(x+y)<0? -(x+y): (x+y); point*p=&hash_table[value]; if(p->index==-1)returnfalse; while(p! =NULL) { if(a[p->index][0]==x&&a[p->index][1]==y)returntrue; p=p->next; } returnfalse; }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- ACM必做50题的解题快速查找 BSearch Hash and so on ACM 50 解题 快速 查找