Trie树 + DFS - CSU 1457 Boggle

Boggle

Problem‘s Link: http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1457



Mean:

给定n个串,有m个询问。

每个询问给你一个4*4的字符矩阵,你可以在这个字符矩阵中任意字符出发,向四个方向走(已走过的不可重复走),走出一个字符串。

如果n个串中有对应的串和走出的字符串相同,那么需要求出:

1.不同长度的串给了不同的权值,n个串中出现的串的总权值是多少?

2.从出现的字符串中找一个最长的出来,如果有多个,找一个字典序最小的。

3.n个串中总共出现了多少个串?

analyse:

Trie树+DFS.

一开始我是将矩阵的dfs串加入到Trie树中,然后用n个串来匹配树,各种TLE。

后来算了一下时间复杂度,很明显将n个串插入到Trie树中,再用矩阵的dfs串去匹配树,这样更优。

当然这样的话就要自己写字典序的比较函数,也很简单,其他地方没什么坑,写的时候细心一点就行。

Time complexity: O(N+M)

Source code: 

/*
* this code is made by crazyacking
* Verdict: Accepted
* Submission Date: 2015-08-27-13.27
* Time: 0MS
* Memory: 137KB
*/
#include <queue>
#include <cstdio>
#include <set>
#include <string>
#include <stack>
#include <cmath>
#include <climits>
#include <map>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long(LL);
typedef unsigned long long(ULL);
const double eps(1e-8);

int score,num;
bool v[5000010],vv[10][10];
int dx[]= {1,1,0,-1,-1,-1,0,1};
int dy[]= {0,1,1,1,0,-1,-1,-1};
int val[]={0,0,0,1,1,2,3,5,11,11,11};
char str[300010][10],Mat[4][5],ans[10],tmp[10];

struct node
{
     node *Next[26];
     int sc,num;
     bool flag;
     node()
     {
           for(int i=0; i<26; ++i) Next[i]=NULL;
           num=0,sc=-1;
     }
} *root;

void Insert(char *s,int id)
{
     node *p=root;
     int i=0,idx;
     while(s[i])
     {
           idx=s[i]-‘A‘;
           if(p->Next[idx]==NULL)
                 p->Next[idx]=new node();
           p=p->Next[idx];
           ++i;
     }
     p->num=id;
     p->sc=val[strlen(s)];
}

void Matching(char *s)
{
     int i=0,idx;
     node *p=root;
     int len=strlen(s);
     while(s[i])
     {
           idx=s[i]-‘A‘;
           if(p->Next[idx]==NULL) break;
           p=p->Next[idx];
           ++i;
     }
     if(v[p->num]==false && p->sc!=-1)
     {
           ++num;
           score+=p->sc;
           v[p->num]=true;
           if(num==1 || (strlen(s)>strlen(ans)) || ((strlen(s)==strlen(ans) && strcmp(s,ans)<0)) )
                 memcpy(ans,s,10);
     }
}

void dfs(int x,int y,int cnt)
{
     if(cnt>8) return;
     tmp[cnt-1]=Mat[x][y];
     tmp[cnt]=‘\0‘;
     Matching(tmp);
     vv[x][y]=true;
     for(int i=0;i<8;++i)
     {
           int xx=x+dx[i];
           int yy=y+dy[i];
           if(vv[xx][yy]!=true && (xx>=0&&xx<4&&yy>=0&&yy<4))
           {
                 vv[x][y]=1;
                 dfs(xx,yy,cnt+1);
                 vv[x][y]=0;
           }
     }
     vv[x][y]=0;
}

int main()
{
     ios_base::sync_with_stdio(false);
     cin.tie(0);
     int n,m;
     scanf("%d",&n);
     root=new node();
     for(int i=0; i<n; ++i)
     {
           scanf("%s",str[i]);
           Insert(str[i],i);
     }
     scanf("%d",&m);
     while(m--)
     {
           memset(v,0,sizeof v);
           score=num=0;
           for(int i=0; i<4; ++i)
                 scanf("%s",Mat[i]);
           for(int i=0; i<4; ++i)
                 for(int j=0; j<4; ++j)
                       dfs(i,j,1);
           printf("%d %s %d\n",score,ans,num);
     }
     return 0;
}
/*

*/

时间: 2024-12-29 07:22:53

Trie树 + DFS - CSU 1457 Boggle的相关文章

Luogu_P2536 [AHOI2005]病毒检测 trie树+dfs

Luogu_P2536 [AHOI2005]病毒检测 ### trie树+dfs 题目链接 这两个符号比较有意思 可以把所有的串都先建到trie树上 然后用病毒的模式串在上面搜索 处理这两个符号就可以通过搜索次序解决 主要可以看代码 问的是非病毒,WA了 一个符号可以不取,又WA了 代码如下: #include<bits/stdc++.h> using namespace std; string bd,w[1010]; int ans,n,trie[250010][10],tot=1,ed[2

poj 2418 Hardwood Species (trie树)

poj   2418   Hardwood Species http://poj.org/problem?id=2418 trie树+dfs 题意: 给你多个单词,问每个单词出现的频率. 方法:通过字典树,将所有单词放入树中,通过dfs遍历(题目要求按ASSIC码顺序输出单词及其频率),dfs可满足 注意:单词中不一定只出现26个英文字母,ASSIC码表共有256个字符 1 #include <stdio.h> 2 #include <string.h> 3 #include &l

BZOJ 3439 Kpm的MC密码 Trie树+可持久化线段树

题目大意:给定n个字符串,对于每个字符串求以这个字符串为后缀的字符串中第k小的编号 首先将字符串反转 那么就变成了对于每个字符串求以这个字符串为前缀的字符串中第k小的编号 然后考虑对字符串排序 那么对于每个字符串以它为前缀的字符串一定是连续的 那么就转化成了区间第k小 这个用可持久化线段树可以解决 排序自然不能直接排 既然是字符串 考虑Trie树+DFS即可 注意字符串有重复的 小心 #include <vector> #include <cstdio> #include <

BZOJ5338 [TJOI2018] Xor 【可持久化Trie树】【dfs序】

题目分析: 很无聊的一道题目.首先区间内单点对应异或值的询问容易想到trie树.由于题目在树上进行,case1将路径分成两段,然后dfs的时候顺便可持久化trie树做询问.case2维护dfs序,对dfs序建可持久化的trie树.这样做的空间复杂度是O(nw),时间复杂度是O(nw). 代码: 1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int maxn=102000; 5 6 int n,q; 7 int v[maxn

[POJ] #1003# 487-3279 : 桶排序/字典树(Trie树)/快速排序

一. 题目 487-3279 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 274040   Accepted: 48891 Description Businesses like to have memorable telephone numbers. One way to make a telephone number memorable is to have it spell a memorable word or

[ACM] POJ 2418 Hardwood Species (Trie树或map)

Hardwood Species Time Limit: 10000MS   Memory Limit: 65536K Total Submissions: 17986   Accepted: 7138 Description Hardwoods are the botanical group of trees that have broad leaves, produce a fruit or nut, and generally go dormant in the winter. Ameri

[ACM] POJ 2418 Hardwood Species (Trie树或者map)

Hardwood Species Time Limit: 10000MS   Memory Limit: 65536K Total Submissions: 17986   Accepted: 7138 Description Hardwoods are the botanical group of trees that have broad leaves, produce a fruit or nut, and generally go dormant in the winter. Ameri

【bzoj4212】神牛的养成计划 Trie树+可持久化Trie树

题目描述 Hzwer成功培育出神牛细胞,可最终培育出的生物体却让他大失所望...... 后来,他从某同校女神 牛处知道,原来他培育的细胞发生了基因突变,原先决定神牛特征的基因序列都被破坏了,神牛hzwer很生气,但他知道基因突变的低频性,说不定还有以下优秀基因没有突变,那么他就可以用限制性核酸内切酶把它们切出来,然后再构建基因表达载体什么的,后面你懂的...... 黄学长现在知道了N个细胞的DNA序列,它们是若干个由小写字母组成的字符串.一个优秀的基因是两个字符串s1和s2,当且仅当s1是某序列

BZOJ 4032 trie树+各种乱搞

思路 : 先对b 的所有后缀建立trie树 第一问 暴力枚举a串的起点 在trie树上跑 找到最短的 第二问 也是暴力枚举a串的起点 a和b顺着暴力匹配就好 第三问 求出来a在第i个位置 加一个字母j 能够到的最近的位置 f[i][j] 到最后就是inf 从f[0][j]DFS 在trie上跟着跑找到最小的deep更新答案 第四问 先按照求f一样同理求出b串 的  g dp[i][j]表示a的前i个位置 b不得不匹配到b的第j个位置             dp[i+1][j]=min(dp[i