zoukankan      html  css  js  c++  java
  • POJ1204 Word Puzzles

    嘟嘟嘟

    翻译洛谷有,但输入格式好像不太一样,注意一下。

    这题我看了5分钟才把题看懂,知道是有关AC自动机的,然而就是想不出来。

    我一直觉得应该把这张图建一个trie树,毕竟图作为主串,然后看模式串是否出现在主串里。

    然而实际上是模式串建trie树。

    然后题中说要判断8个方向是否有模式串出现,那么就把图中8个方向形成的字符串都放到AC自动机上跑一下。我刚开始以为会超时,但复杂度最多为O(8 * n2),只有8e6,而AC自动机是线性的,所以TLE不了。

    关于遍历八个方向上的字符串,写起来得动动脑子,可以联想到bfs或dfs跑图的时候用到的方向数组。

    然后有因为AC自动机找到的匹配点是模式串的末尾,所以我们还要在这个方向上减去模式串的长度。

    然后就是AC自动机的板子了。

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<algorithm>
      4 #include<cmath>
      5 #include<cstring>
      6 #include<cstdlib>
      7 #include<cctype>
      8 #include<stack>
      9 #include<queue>
     10 #include<vector>
     11 using namespace std;
     12 #define enter puts("")
     13 #define space putchar(' ')
     14 #define Mem(a, x) memset(a, x, sizeof(a))
     15 #define rg register
     16 typedef long long ll;
     17 typedef double db;
     18 const int INF = 0x3f3f3f3f;
     19 const db eps = 1e-8;
     20 const int maxn = 1e3 + 5;
     21 inline ll read()
     22 {
     23   ll ans = 0;
     24   char ch = getchar(), las = ' ';
     25   while(!isdigit(ch)) las = ch, ch = getchar();
     26   while(isdigit(ch)) ans = ans * 10 + ch - '0', ch = getchar();
     27   if(las == '-') ans = -ans;
     28   return ans;
     29 }
     30 inline void write(ll x)
     31 {
     32   if(x < 0) putchar('-'), x = -x;
     33   if(x >= 10) write(x / 10);
     34   putchar(x % 10 + '0');
     35 }
     36 
     37 int n, m, w;
     38 char a[maxn][maxn], s[maxn];
     39 
     40 int len[maxn];
     41 int ch[maxn * maxn][26], val[maxn * maxn], f[maxn * maxn], cnt = 0;
     42 int getnum(char c)
     43 {
     44   return c - 'A';
     45 }
     46 void insert(int id, char *s)
     47 {
     48   len[id] = strlen(s);
     49   int now = 0;
     50   for(int i = 0; i < len[id]; ++i)
     51     {
     52       int c = getnum(s[i]);
     53       if(!ch[now][c]) ch[now][c] = ++cnt;
     54       now = ch[now][c];
     55     }
     56   val[now] = id;
     57 }
     58 void build()
     59 {
     60   queue<int> q;
     61   for(int i = 0; i < 26; ++i) if(ch[0][i]) q.push(ch[0][i]);
     62   while(!q.empty())
     63     {
     64       int now = q.front(); q.pop();
     65       for(int i = 0; i < 26; ++i)
     66     {
     67       if(ch[now][i]) f[ch[now][i]] = ch[f[now]][i], q.push(ch[now][i]);
     68       else ch[now][i] = ch[f[now]][i];
     69     }
     70     }
     71 }
     72 const int dx[] = {-1, -1, 0, 1, 1, 1, 0, -1}, dy[] = {0, 1, 1, 1, 0, -1, -1, -1};
     73 struct Node
     74 {
     75     int x, y, d;
     76 }ans[maxn];
     77 void query(int x, int y, int d)
     78 {
     79     int newx = x, newy = y, now = 0;
     80     do
     81     {
     82         int c = getnum(a[newx][newy]);
     83         now = ch[now][c];
     84         for(int j = now; j && val[j] != -1; j = f[j]) if(val[j] > 0)
     85         {
     86             ans[val[j]].x = newx - (len[val[j]] - 1) * dx[d];
     87             ans[val[j]].y = newy - (len[val[j]] - 1) * dy[d];
     88             ans[val[j]].d = d;
     89             val[j] = -1;
     90         }
     91         newx += dx[d]; newy += dy[d];
     92     }while(newx >= 0 && newx < n && newy >= 0 && newy < m);
     93 }
     94 
     95 int main()
     96 {
     97       n = read(); m = read(); w = read();
     98       for(int i = 0; i < n; ++i) scanf("%s", a[i]);
     99       for(int i = 1; i <= w; ++i)
    100         {
    101           scanf("%s", s);
    102           insert(i, s);
    103         }
    104       build();
    105       for(int i = 0; i < n; ++i)
    106       {
    107           query(i, 0, 2); query(i, m - 1, 6);    
    108           query(i, 0, 1); query(i, m - 1, 5);
    109           query(i, 0, 3); query(i, m - 1, 7);
    110       }
    111       for(int i = 0; i < m; ++i)
    112       {
    113           query(n - 1, i, 0); query(0, i, 4);
    114           query(n - 1, i, 1); query(0, i, 5);
    115           query(0, i, 3); query(n - 1, i, 7);
    116       }
    117       for(int i = 1; i <= w; ++i) printf("%d %d %c
    ", ans[i].x, ans[i].y, ans[i].d + 'A');
    118   return 0;
    119 }
    View Code

    USACO上是多组数据,所以一定得清零,而且必须是动态的。然后我因为根节点的所有出边没清零而莫名TLE好久。

    放一个比较好看的代码。

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<algorithm>
      4 #include<cmath>
      5 #include<cstring>
      6 #include<cstdlib>
      7 #include<cctype>
      8 #include<stack>
      9 #include<queue>
     10 #include<vector>
     11 using namespace std;
     12 #define enter puts("")
     13 #define space putchar(' ')
     14 #define Mem(a, x) memset(a, x, sizeof(a))
     15 #define rg register
     16 typedef long long ll;
     17 typedef double db;
     18 const int INF = 0x3f3f3f3f;
     19 const db eps = 1e-8;
     20 const int maxn = 1e3 + 5;
     21 inline ll read()
     22 {
     23   ll ans = 0;
     24   char ch = getchar(), las = ' ';
     25   while(!isdigit(ch)) las = ch, ch = getchar();
     26   while(isdigit(ch)) ans = ans * 10 + ch - '0', ch = getchar();
     27   if(las == '-') ans = -ans;
     28   return ans;
     29 }
     30 inline void write(ll x)
     31 {
     32   if(x < 0) putchar('-'), x = -x;
     33   if(x >= 10) write(x / 10);
     34   putchar(x % 10 + '0');
     35 }
     36 
     37 int n, m, w;
     38 char a[maxn][maxn], s[maxn];
     39 
     40 int len[maxn];
     41 int ch[maxn * maxn][26], val[maxn * maxn], f[maxn * maxn], cnt = 0;
     42 inline int getnum(const char& c)
     43 {
     44   return c - 'A';
     45 }
     46 inline void insert(const int& id, char *s)
     47 {
     48   int now = 0;
     49   for(; *s; s++)
     50     {
     51       int c = getnum(*s);
     52       if(!ch[now][c])
     53     {
     54      ch[now][c] = ++cnt;
     55      val[cnt] = f[cnt] = 0;
     56      for(rg int j = 0; j < 26; ++j) ch[cnt][j] = 0;
     57     }
     58       now = ch[now][c];
     59     }
     60   val[now] = id;
     61   return;
     62 }
     63 queue<int> q;
     64 inline void build()
     65 {
     66   for(rg int i = 0; i < 26; ++i) if(ch[0][i]) q.push(ch[0][i]);
     67   while(!q.empty())
     68     {
     69       int now = q.front(); q.pop();
     70       for(rg int i = 0; i < 26; ++i)
     71     {
     72       if(ch[now][i]) f[ch[now][i]] = ch[f[now]][i], q.push(ch[now][i]);
     73       else ch[now][i] = ch[f[now]][i];
     74     }
     75     }
     76   return;
     77 }
     78 const int dx[] = {-1, -1, 0, 1, 1, 1, 0, -1}, dy[] = {0, 1, 1, 1, 0, -1, -1, -1};
     79 struct Node
     80 {
     81     int x, y, d;
     82 }ans[maxn];
     83 void query(const int& x, const int& y, const int& d)
     84 {
     85     int newx = x, newy = y, now = 0;
     86     do
     87     {
     88         int c = getnum(a[newx][newy]);
     89         now = ch[now][c];
     90         for(rg int j = now; j && val[j] != -1; j = f[j]) if(val[j] > 0)
     91         {
     92             ans[val[j]].x = newx - (len[val[j]] - 1) * dx[d];
     93             ans[val[j]].y = newy - (len[val[j]] - 1) * dy[d];
     94             ans[val[j]].d = d;
     95             val[j] = -1;
     96         }
     97         newx += dx[d]; newy += dy[d];
     98     }while(newx >= 0 && newx < n && newy >= 0 && newy < m);
     99 }
    100 
    101 int main()
    102 {
    103     int T = read();
    104     while(T--)
    105      {
    106           cnt = 0;
    107       for(int i = 0; i < 26; ++i) ch[0][i] = 0;
    108       n = read(); m = read(); w = read();
    109       for(rg int i = 0; i < n; ++i) scanf("%s", a[i]);
    110       for(rg int i = 1; i <= w; ++i)
    111         {
    112           scanf("%s", s);
    113           len[i] = strlen(s);
    114           insert(i, s);
    115         }
    116         build();
    117       for(rg int i = 0; i < n; ++i)
    118       {
    119           query(i, 0, 2); query(i, m - 1, 6);    //hengzhe
    120           query(i, 0, 1); query(i, m - 1, 5);
    121           query(i, 0, 3); query(i, m - 1, 7);
    122       }
    123       for(rg int i = 0; i < m; ++i)
    124       {
    125           query(n - 1, i, 0); query(0, i, 4);
    126           query(n - 1, i, 1); query(0, i, 5);
    127           query(0, i, 3); query(n - 1, i, 7);
    128       }
    129       for(rg int i = 1; i <= w; ++i) printf("%d %d %c
    ", ans[i].x, ans[i].y, ans[i].d + 'A');
    130         if(T) enter;
    131     }
    132   return 0;
    133 }
    View Code
  • 相关阅读:
    用来验证字符串的规则引擎
    C++基本错误:
    web service传递stream二进制对象的解决方法
    安装EnterpriseLibrary4.1后遇到PresentationBuildTasks找不到的问题
    关于NHibernate示例程序QuickStart无法运行的问题
    关于iframe.document
    .NET下转换日期格式为中文大写
    History(历史)命令用法 15 例
    防火墙技术发展趋势浅析
    MIME类型大全
  • 原文地址:https://www.cnblogs.com/mrclr/p/9769911.html
Copyright © 2011-2022 走看看