题目大意;原题链接

给定一个字符串矩阵和待查找的单词,可以朝8个不同的方向查找,输出待查找单词第一个字母在矩阵中出现的位置和该单词被查到的方向.

A~H代表8个不同的方向,A代表正北方向,其他依次以45度角的方向顺时针增加.

解题思路:

解法一:Trie树暴搜

因为不查询重复单词,所以dfs(int u,int i,int j,int k)函数中当已经查询到单词时,val[u]可以置零做标记.

  1. #include<cstdio>
  2. #include<cstring>
  3. #define maxn 200010
  4. using namespace std;
  5. bool vis[];
  6. int n,m,w,x,y,sz=;//sz得为全局变量
  7. char str[][],word[];
  8. int val[maxn],out[][];
  9. int dir[][]={-,,-,,,,,,,,,-,,-,-,-};//顺时针
  10. struct Trie
  11. {
  12. int next[];
  13. }trie[maxn];
  14.  
  15. void insert(char *s,int k)
  16. {
  17. int u=,len=strlen(s);
  18. for(int i=;i<len;i++){
  19. int id=s[i]-'A';
  20. if(!trie[u].next[id])
  21. trie[u].next[id]=sz++;
  22. u=trie[u].next[id];
  23. }
  24. val[u]=k;//u为结点编号,k为单词编号
  25. }
  26. void dfs(int u,int i,int j,int k)//k记录方向
  27. {
  28. if(u==||i<||i>=n||j<||j>=m) return;//该语句之前放在if(val[u])条件之后,WA
  29. if(val[u]){
  30. out[val[u]][]=x;
  31. out[val[u]][]=y;
  32. out[val[u]][]=k;
  33. val[u]=;//做标记,因为不查询重复单词
  34. }
  35. int id=str[i+dir[k][]][j+dir[k][]]-'A';
  36. dfs(trie[u].next[id],i+dir[k][],j+dir[k][],k);//必须得朝同一方向搜索
  37. }
  38.  
  39. int main()
  40. {
  41. scanf("%d%d%d",&n,&m,&w);
  42. for(int i=;i<n;i++)
  43. scanf("%s",str[i]);
  44. for(int i=;i<=w;i++){
  45. scanf("%s",word);
  46. insert(word,i);
  47. vis[word[]-'A']=;
  48. }
  49. for(int i=;i<n;i++){
  50. for(int j=;j<m;j++){
  51. if(vis[str[i][j]-'A']){
  52. for(int k=;k<;k++){
  53. x=i,y=j;//记录下最初的位置,从Trie树根开始向下搜索
  54. dfs(trie[].next[str[i][j]-'A'],i,j,k);
  55. }
  56. }
  57. }
  58. }
  59. for(int i=;i<=w;i++)
  60. printf("%d %d %c\n",out[i][],out[i][],out[i][]+'A');
  61. return ;
  62. }

解法二:AC自动机

参考链接:哔哩哔哩算法讲堂

  1. #include<queue>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cstring>
  5. #define inf 0x3f3f3f3f
  6. using namespace std;
  7. char str[][],word[];
  8. int n,m,w;
  9. int dir[][]={-,,-,,,,,,,,,-,,-,-,-};//顺时针
  10. char ch[]="ABCDEFGH";
  11. int pos[][];
  12. struct TrieNode{
  13. int id;//记录第几个字符串
  14. TrieNode *next[],*fail;
  15. TrieNode(){
  16. id=,fail=;
  17. memset(next,,sizeof(next));
  18. }
  19. }*root;
  20.  
  21. void InsertNode(char *s,int id)
  22. {
  23. int len=strlen(s)-;
  24. TrieNode *p=root;
  25. while(len>=){//这里将s数组倒着插入字典树,方便匹配时记录匹配的终点即原串的起始点
  26. if(!p->next[s[len]-'A'])
  27. p->next[s[len]-'A']=new TrieNode;
  28. p=p->next[s[len--]-'A'];
  29. }
  30. p->id=id;//id记录单词编号
  31. }
  32. void Build_AC()
  33. {
  34. TrieNode *p,*next;
  35. queue<TrieNode* > que;
  36. que.push(root);
  37. while (!que.empty()){
  38. p=que.front();
  39. que.pop();
  40. for(int i=;i<;i++){
  41. if(p->next[i]){
  42. if(p==root) p->next[i]->fail=root;
  43. else{
  44. TrieNode *temp=p->fail;
  45. while(temp){
  46. if(temp->next[i]){//temp始终代表next[i]的爸爸,有next[i]这个儿子
  47. p->next[i]->fail=temp->next[i];
  48. break;//寻找最长后缀
  49. }
  50. temp=temp->fail;
  51. }
  52. if(!temp) p->next[i]->fail=root;
  53. }
  54. que.push(p->next[i]);
  55. }
  56. }
  57. }
  58. }
  59. void Query(int x,int y,int d,int di)
  60. {
  61. TrieNode *p=root,*next;
  62. while(x>=&&y>=&&x<n&&y<m){
  63. while(p&&!p->next[str[x][y]-'A']) p=p->fail;
  64. if(!p) p=root;
  65. else p=p->next[str[x][y]-'A'];
  66. next=p;
  67. while(next!=root){
  68. if(next->id){//记录原串被匹配的起始点
  69. int k=next->id;
  70. if(pos[k][]>x||(pos[k][]==x&&pos[k][]>y)){
  71. pos[k][]=x;
  72. pos[k][]=y;
  73. pos[k][]=di;//记录单词整体朝向
  74. }
  75. }
  76. next=next->fail;
  77. }
  78. x+=dir[d][];
  79. y+=dir[d][];
  80. }
  81. }
  82. void Free(TrieNode *p)
  83. {
  84. for(int i=;i<;i++){
  85. if(p->next[i])
  86. Free(p->next[i]);
  87. }
  88. delete p;
  89. }
  90.  
  91. int main(){
  92. scanf("%d%d%d",&n,&m,&w);
  93. root=new TrieNode;
  94. for(int i=;i<n;i++)
  95. scanf("%s",str[i]);
  96. for(int i=;i<=w;i++){
  97. scanf("%s",&word);
  98. InsertNode(word,i);
  99. pos[i][]=pos[i][]=inf;
  100. }
  101. Build_AC();
  102. for(int i=;i<m;i++){
  103. Query(,i,,),Query(n-,i,,);
  104. Query(,i,,),Query(n-,i,,);
  105. Query(,i,,),Query(n-,i,,);
  106. }//从矩阵上下左右四条边枚举8个方向
  107. for(int i=;i<n;i++){
  108. Query(i,,,),Query(i,m-,,);
  109. Query(i,,,),Query(i,m-,,);
  110. Query(i,,,),Query(i,m-,,);
  111. }
  112. for(int i=;i<=w;i++)
  113. printf("%d %d %c\n",pos[i][],pos[i][],ch[pos[i][]]);
  114. Free(root);
  115. }

后缀数组倍增解法过一段时间补上

PKU 1204 Word Puzzles(AC自动机)的更多相关文章

  1. [poj] 1204 Word Puzzles || AC自动机

    原题 给个X*Y的字符串矩阵,W个询问,对每个询问输出这个串出现的位置及方向,共有8个方向,顺时针开始分别用A~H表示 AC自动机的板子题. 对于待匹配串建一个自动机,然后从矩阵的四周分别沿八个方向跑 ...

  2. pku1204 Word Puzzles AC自动机 二维字符串矩阵8个方向找模式串的起点坐标以及方向 挺好的!

    /** 题目:pku1204 Word Puzzles 链接:http://poj.org/problem?id=1204 题意:给定一个L C(C <= 1000, L <= 1000) ...

  3. POJ 1204 Word Puzzles | AC 自动鸡

    题目: 给一个字母矩阵和几个模式串,矩阵中的字符串可以有8个方向 输出每个模式串开头在矩阵中出现的坐标和这个串的方向 题解: 我们可以把模式串搞成AC自动机,然后枚举矩阵最外围一层的每个字母,向八个方 ...

  4. 【 POJ - 1204 Word Puzzles】(Trie+爆搜|AC自动机)

    Word Puzzles Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 10782 Accepted: 4076 Special ...

  5. [POJ 1204]Word Puzzles(Trie树暴搜&amp;AC自己主动机)

    Description Word puzzles are usually simple and very entertaining for all ages. They are so entertai ...

  6. POJ 题目1204 Word Puzzles(AC自己主动机,多个方向查询)

    Word Puzzles Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 10244   Accepted: 3864   S ...

  7. POJ 1204 Word Puzzles(AC自动机)

    这题的数据卡在,如下: 5 5 3 ABCDE FGHIJ KLMNO PQRST UVWXY PQR RS RST puzzle中间的行中可以包含要查询的多个单词.这个问题很好解决,SearchDf ...

  8. poj 1204 Word Puzzles(字典树)

    题目链接:http://poj.org/problem?id=1204 思路分析:由于题目数据较弱,使用暴力搜索:对于所有查找的单词建立一棵字典树,在图中的每个坐标,往8个方向搜索查找即可: 需要注意 ...

  9. 【POJ】1204 Word Puzzles

    这道题目各种wa.首先是错了一个坐标,居然没测出来.然后是剪枝错误.搜索pen时就返回,可能还存在串pen*. #include <cstdio> #include <cstring ...

随机推荐

  1. RAID的简单说明

    RAID,为 Redundant Arrays of Independent Disks 的简称,中文为廉价※冗余磁盘阵列 . 磁盘阵列 其实也分为软阵列 (Software Raid) 和硬阵列 ( ...

  2. bootstrap基础学习六篇

    bootstrap按钮 类 描述 .btn 为按钮添加基本样式 .btn-default 默认/标准按钮 .btn-primary 原始按钮样式(未被操作) .btn-success 表示成功的动作 ...

  3. (转)word尾注引文添加方式及相关问题

    word引文添加方式:http://www.office68.com/word/word-reference-add.html word通配符:http://www.3lian.com/edu/201 ...

  4. Vim相关优化和配置

    升级pythonwget https://www.python.org/ftp/python/3.6.5/Python-3.6.5.tgztar -xvf Python-3.6.5.tgzcd Pyt ...

  5. Linux命令之乐--md5sum

    md5sum命令用于生成和校验文件的md5值.它会逐位对文件的内容进行校验,它常用于检查文件的完整性. 读取文件的MD5值 [root@new ~]# md5sum /usr/local/sbin/* ...

  6. 第四篇:new和delete的基本用法

    前言 new和delete是C++中用来动态管理内存分配的运算符,其用法较为灵活.如果你对它们的几种不同用法感到困惑,混淆,那么接着看下去吧. 功能一:动态管理单变量/对象空间 下面例子使用new为单 ...

  7. ndarray 布尔类型矩阵中统计Ture 的次数

    对象:NumPy数组或矩阵,eg. data的元素为True和False numpy.sum(data) #统计data中True的个数numpy.count_nonzero(data) #统计dat ...

  8. rimraf删除gulp的模块插件

    1.安装:npm install -g rimraf(全局安装),如果安装了cnpm,也可使用cnpm install -g rimraf 命令 2.使用:先定位目标文件夹的父级目录,然后命令行输入r ...

  9. 为什么Objective-C很难

    转自:http://mobile.51cto.com/hot-322261.htm   2012-03-07 13:43 junwong 开源中国社区 字号:T | T 作为一个Objective-C ...

  10. android studio升级时提示 Connection failed. Please check your network connection and try again

    原文地址 http://www.eyeapk.com/android-studio-update.html Mac OSX中修改文件路径为 bin/idea.vmoptions ,添加如下内容,如果无 ...