ACM必做50题的解题-快速查找(B-Search, Hash and so on)

更新时间:2024-07-01 03:36:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

POJ 2503 Babelfish

题目大意很简单,就是给你字典的对应信息,然后给你查询条件要求你输出字典查询结果,如果字符串没有在字典中则输出\。

恩,学到了一个新的函数bsearch(),可以进行二分查找。先对字典使用qsort排序然后再使用bsearch()查找字符串即可。

还学到了一个输入函数sscanf(),可以从一个字符串中读取内容,格式如下 sscanf (string str, string format [, string var1...])

#include #include #include

typedef struct {

char en[11]; char fn[11]; }dict;

dict a[100001];

/* 定义qsort比较函数 */

int q_cmp(const void * a,const void *b) {

return strcmp(((dict*)a)->fn, ((dict*)b)->fn); }

/* 定义bsearch比较函数 */

int b_cmp(const void* a, const void* b) {

return strcmp((char*)a, ((dict*)b)->fn); }

int main() {

char str[30]; int i, 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, \ i++; }

/* 查询开始时进行查询 */ else {

/* 二分查找指定字符串 */

p = (dict*) bsearch(str, a, i, sizeof(dict), b_cmp); /* 找到则输出结果 */ if (p) {

puts(p->en); }

/* 找不到输出\ else {

puts(\ } } }

//system(\ return 0; }

POJ 2513 Colored Sticks 欧拉通路+并查集+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 using namespace std;

const int max_size=500001; char s1[11],s2[11]; int p[max_size]; int r[max_size];

int degree[max_size]; int num=1;

struct TreeNode {

int id;//the id of the string TreeNode * next[27]; TreeNode () {

id=0;

for(int i=0;i<27;i++) next[i]=NULL; } };

TreeNode * root;

void insert(char *s ,TreeNode * root) {

TreeNode *p = root; int i = 0;

int l = strlen(s); for(i=0;i

if(p->next[s[i]-'a']==NULL)

p->next[s[i]-'a']=new TreeNode; p=p->next[s[i]-'a']; }

if(p->id==0)//first insert p->id = num++; }

int search(char *s,TreeNode *root) {

TreeNode * p = root; if(p==NULL)

return -1; int i=0;

int l = strlen(s); for(i=0;i

if(p->next[s[i]-'a']==NULL) return -1; else

p=p->next[s[i]-'a']; }

return p->id; }

void make_set(int x) {

p[x]=x; r[x]=1; }

int find_set(int x) {

if(p[x]!=x)

p[x]=find_set(p[x]); return p[x]; }

void union_set(int x,int y) {

if(r[x]>r[y]) p[y]=x; else if(r[x]

{

r[y]++; p[x]=y; } }

int main() {

root = new TreeNode; memset(p,0,sizeof(p));

memset(degree,0,sizeof(degree)); while(scanf(\ {

insert(s1,root); insert(s2,root);

int id1 = search(s1,root); int id2 = 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)); }

int i = 0; int sum=0;

//if the num of nodes whose degree is odd are more than 2. for(i=1;i

if(degree[i]%2!=0)sum++; if(sum>2) {

cout<<\ return 0; } }

//if the g is joint. for(i=1;i

if(find_set(i) != find_set(1)) {

cout<<\ return 0 ; }

cout<<\

}

poj 1035 Spell checker

开始做字符串的题目,本人觉得最头痛噶野,好鬼唔锺意处理字符串噶野。不过唯有硬住头皮上啦。

呢条题有个奇怪噶地方,就系用STL做的话,点都系TLE,后来改翻用C语言甘样慢慢搞先过,重要用左将近1s.

注意:(1)用另一个字符数组记录字典,然后排序,用于二分查找的。

(2)先处理与被检查数组相同长度的,然后系,比距长的,最后系比距短的。

(3)数组开得足够大啦

#include #include #include using namespace std;

int cmp(const void *p, const void *q) { return strcmp((char *) p, (char *) q); }

struct s {

char word[20]; int len; } str1[10005];

char str2[10005][20], bc[20], ch[20], *p; int bcl, n;

void input() { int i = 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); }

void solve() { int i, j, k;

while (strcmp(gets(bc), \ bcl = strlen(bc);

p = (char *) bsearch(&bc, str2 + 1, n, sizeof (str2[0]), cmp); if (p)

cout << bc << \ else {

cout << bc << \

for (i = 1; i <= n; i++) { if (str1[i].len == bcl) { int flag = 0;

for (j = 0; j < str1[i].len; j++) { if (str1[i].word[j] != bc[j]) flag++; }

if (flag < 2) cout << \ } else if (bcl == str1[i].len + 1) {

for (j = 0; j < bcl; j++) { strcpy(ch, bc);

for (k = j; k < bcl; k++) ch[k] = ch[k + 1];

//cout<

} else if (bcl == str1[i].len - 1) {

for (j = 0; j < str1[i].len; j++) { strcpy(ch, str1[i].word);

for (k = j; k < str1[i].len; k++) ch[k] = ch[k + 1];

//cout<

printf(\ break; } }

} }

cout << endl; } } }

int main() { input(); solve(); return 0; }

POJ 1200 Crazy Search

这个是说一段字符串 有nc种字符组成 问长度为n的不同的字符串有多少个 非常关键的一条信息是 nc^n最多只有16 000 000 so 我们用nc进制的HASH来做

#include #include int n,nc;

char str[20000000]; char asca[128]; int hash[16000005];

int main() {

while(scanf(\ {

scanf(\ int i=0; int j; int key=0; while(str[i]) {

if(asca[str[i]]==0) asca[str[i]]=++key; i++;

if(key==nc) break;

}

int len=strlen(str); int sum; int cnt=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(\

} }

POJ 2002 hash(枚举+哈希)

简单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 using namespace std; struct point {

point() {

index=-1;

next=NULL; }

point(int index,point* next) {

this->index=index; this->next=next; }

int index; point* next; };

int a[1001][2];

bool find(point hash_table[],int,int); int main() {

int n,value;

while(scanf(\ {

long result=0;

point hash_table[40001]; for(int e=0;e

scanf(\ 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=new point(e,NULL); } }

for(int x=0;x

int d_x=a[x][0]-a[y][0]; int d_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(\ }

return 0; }

bool find(point hash_table[40001],int x,int y) {

int value=(x+y)<0?-(x+y):(x+y); point* p=&hash_table[value]; if(p->index==-1)return false; while(p!=NULL) {

if(a[p->index][0]==x&&a[p->index][1]==y)return true; p=p->next; }

return false; }

printf(\ }

return 0; }

bool find(point hash_table[40001],int x,int y) {

int value=(x+y)<0?-(x+y):(x+y); point* p=&hash_table[value]; if(p->index==-1)return false; while(p!=NULL) {

if(a[p->index][0]==x&&a[p->index][1]==y)return true; p=p->next; }

return false; }

本文来源:https://www.bwwdw.com/article/cwy.html

Top