http://acm.hust.edu.cn/vjudge/problem/33057
题意:在二维文本串T中查找一个二维模板串P出现了多少次。
题解:
拆分模板串P的每一行,建AC自动机。
拆分文本串T的每一行,在自动机中与P匹配,ct[i][j]表示以点(i,j)为左上角、与P等大的矩形有多少个对应的行与P匹配。
最后ct[i][j]==P的行数的i,j就是一个匹配点,ans++。
注意:1.原本我在trie的叶子用动态数组维护了一个表示这一行是P的第几行的数组,但是超时了,后来看了LRJ的代码,改成了用一个nt[i]来表示重复的行的下一行,就A了。
2.注意在ct[i][j]里加的时候判断i,j是否大于0.
1 #include<cstdio>
2 #include<cstdlib>
3 #include<cstring>
4 #include<iostream>
5 #include<queue>
6 #include<vector>
7 using namespace std;
8
9 int n,m,num,ans;
10 int ct[1100][1100],nt[110];
11 char s[1100][1100],ss[1100][1100];
12 struct node{
13 int son[30];
14 int fail,ed;
15 }a[110*110];
16 queue<int> q;
17
18 void clear(int x)
19 {
20 a[x].fail=a[x].ed=0;
21 memset(a[x].son,0,sizeof(a[x].son));
22 }
23
24 void trie(char *c,int id)
25 {
26 int l=strlen(c);
27 int x=0;
28 for(int i=0;i<l;i++)
29 {
30 int t=c[i]-‘a‘+1;
31 if(!a[x].son[t])
32 {
33 num++;
34 clear(num);
35 a[x].son[t]=num;
36 }
37 x=a[x].son[t];
38 }
39 if(!a[x].ed) a[x].ed=id;
40 }
41
42 void buildAC()
43 {
44 while(!q.empty()) q.pop();
45 for(int i=1;i<=26;i++)
46 if(a[0].son[i]) q.push(a[0].son[i]);
47 while(!q.empty())
48 {
49 int x=q.front();q.pop();
50 int fail=a[x].fail;
51 for(int i=1;i<=26;i++)
52 {
53 int y=a[x].son[i];
54 if(y)
55 {
56 a[y].fail=a[fail].son[i];
57 q.push(y);
58 }
59 else a[x].son[i]=a[fail].son[i];
60 }
61 }
62 }
63
64 void find(char *c,int id)
65 {
66 int l=strlen(c);
67 int x=0;
68 for(int i=0;i<l;i++)
69 {
70 int t=c[i]-‘a‘+1;
71 if(!a[x].son[t]) x=0;
72 x=a[x].son[t];
73 int x0=id,y0=(i+1)-m+1;
74 int p=a[x].ed;
75 while(p)
76 {
77 int xx=x0-p+1,yy=y0;
78 if(xx>=1 && yy>=1)//注意!!没有就WA!!
79 {
80 ct[xx][yy]++;
81 if(ct[xx][yy]>=n) ans++;
82 }
83 p=nt[p];
84 }
85 }
86 }
87
88 int main()
89 {
90 freopen("a.in","r",stdin);
91 freopen("a.out","w",stdout);
92 int T;
93 scanf("%d",&T);
94 while(T--)
95 {
96 num=ans=0;
97 clear(0);
98 memset(ct,0,sizeof(ct));
99 memset(nt,0,sizeof(nt));//用nt数组(next)优化,不然就TLE。
100 int x,y;
101 scanf("%d%d",&x,&y);
102 for(int i=1;i<=x;i++)
103 {
104 scanf("%s",ss[i]);
105 }
106 scanf("%d%d",&n,&m);
107 for(int i=1;i<=n;i++)
108 {
109 scanf("%s",s[i]);
110 trie(s[i],i);
111 }
112 for(int i=1;i<=n;i++)
113 for(int j=i+1;j<=n;j++)
114 {
115 if(strcmp(s[i],s[j])==0) {nt[i]=j;break;}
116 }
117 buildAC();
118 for(int i=1;i<=x;i++) find(ss[i],i);
119 printf("%d\n",ans);
120 }
121 return 0;
122 }
【uva11019-Matrix Matcher】AC自动机+优化+记录
原文:http://www.cnblogs.com/KonjakJuruo/p/5686442.html