码迷,mamicode.com
首页 > 其他好文 > 详细

UVa 11019 (AC自动机 二维模式串匹配) Matrix Matcher

时间:2015-04-05 21:44:27      阅读:127      评论:0      收藏:0      [点我收藏+]

标签:

就向书上说得那样,如果模式串P的第i行出现在文本串T的第r行第c列,则cnt[r-i][c]++;

还有个很棘手的问题就是模式串中可能会有相同的串,所以用repr[i]来记录第i个模式串P[i]第一次出现的位置。如果repr[i] == i,说明这个模式串之前没有重复过,可以加进自动机里去。有重复的话,把这些重复的模式串组织成一个链表,用next把它们连接起来。

所以在统计cnt的时候,匹配到的模式串可能会作为匹配的第i行,也可能是next[i]行,next[next[i]]行等等。

技术分享
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <queue>
  4 using namespace std;
  5 
  6 int n, m, x, y, tr;
  7 const int maxx = 100 + 10;
  8 const int maxn = 1000 + 10;
  9 const int maxnode = 10000 + 10;
 10 const int sigma_size = 26;
 11 char T[maxn][maxn], P[maxx][maxx];
 12 int cnt[maxn][maxn];
 13 int repr[maxx];
 14 int next[maxx];
 15 
 16 struct AhoCorasickAutomata
 17 {
 18     int ch[maxnode][sigma_size];
 19     int f[maxnode];
 20     int last[maxnode];
 21     int val[maxnode];
 22     int sz;
 23 
 24     void init() { sz = 1; memset(ch[0], 0, sizeof(ch[0])); }
 25 
 26     inline int idx(char c) { return c - a; }
 27 
 28     void insert(char* s, int v)
 29     {
 30         int u = 0, n = strlen(s);
 31         for(int i = 0; i < n; i++)
 32         {
 33             int c = idx(s[i]);
 34             if(!ch[u][c])
 35             {
 36                 memset(ch[sz], 0, sizeof(ch[sz]));
 37                 val[sz] = 0;
 38                 ch[u][c] = sz++;
 39             }
 40             u = ch[u][c];
 41         }
 42         val[u] = v;
 43     }
 44 
 45     void match(int i, int j)
 46     {
 47         int c = i - y + 1;
 48         int pr = repr[val[j] - 1];
 49         while(pr >= 0)
 50         {
 51             if(tr - pr >= 0) cnt[tr-pr][c]++;
 52             pr = next[pr];
 53         }
 54     }
 55 
 56     void print(int i, int j)
 57     {//在文本串的第i列匹配到单词节点j
 58         if(j)
 59         {
 60             match(i, j);
 61             print(i, last[j]);
 62         }
 63     }
 64 
 65     void find(char* T)
 66     {
 67         int j = 0, n = strlen(T);
 68         for(int i = 0; i < n; i++)
 69         {
 70             int c = idx(T[i]);
 71             while(j && !ch[j][c]) j = f[j];
 72             j = ch[j][c];
 73             if(val[j]) print(i, j);
 74             else if(val[last[j]]) print(i, last[j]);
 75         }
 76     }
 77 
 78     void getFail()
 79     {
 80         queue<int> q;
 81         f[0] = 0;
 82         for(int c = 0; c < sigma_size; c++)
 83         {
 84             int u = ch[0][c];
 85             if(u) { f[u] = 0; last[u] = 0; q.push(u); }
 86         }
 87         while(!q.empty())
 88         {
 89             int r = q.front(); q.pop();
 90             for(int c = 0; c < sigma_size; c++)
 91             {
 92                 int u = ch[r][c];
 93                 if(!u) continue;
 94                 q.push(u);
 95                 int v = f[r];
 96                 while(v && !ch[v][c]) v = f[v];
 97                 f[u] = ch[v][c];
 98                 last[u] = val[f[u]] ? f[u] : last[f[u]];
 99             }
100         }
101     }
102 }ac;
103 
104 int main()
105 {
106     //freopen("in.txt", "r", stdin);
107 
108     int test;
109     scanf("%d", &test);
110     while(test--)
111     {
112         scanf("%d%d", &n, &m);
113         for(int i = 0; i < n; i++) scanf("%s", T[i]);
114         scanf("%d%d", &x, &y);
115         ac.init();
116         for(int i = 0; i < x; i++)
117         {
118             repr[i] = i;
119             next[i] = -1;
120             scanf("%s", P[i]);
121             for(int j = 0; j < i; j++) if(strcmp(P[i], P[j]) == 0)
122             {
123                 repr[i] = j;
124                 next[i] = next[j];
125                 next[j] = i;
126                 break;
127             }
128             if(repr[i] == i) ac.insert(P[i], i+1);
129         }
130         ac.getFail();
131         memset(cnt, 0, sizeof(cnt));
132         for(tr = 0; tr < n; tr++) ac.find(T[tr]);
133 
134         int ans = 0;
135         for(int i = 0; i < n; i++)
136             for(int j = 0; j < m; j++)
137                 if(cnt[i][j] == x) ans++;
138         printf("%d\n", ans);
139     }
140 
141     return 0;
142 }
代码君

 

UVa 11019 (AC自动机 二维模式串匹配) Matrix Matcher

标签:

原文地址:http://www.cnblogs.com/AOQNRMGYXLMV/p/4394728.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!