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 }
时间: 2024-11-10 11:41:31