AC自动机(Matrix Matcher,UVA 11019)
2016-12-15 15:03
274 查看
看到二维的,还以为有什么二维字典树,什么字典树套字典树之类的鬼东西。其实就是建立一个字典树,然后对每行进行匹配,然后再把匹配结果刷表在一个二维数组里。
最后看看二维数组的状况就好了。
具体来讲,就是说如果在i行j列处完成了第k个字符串的匹配,那就在cnt[i-k][j-Y+1]处++。最后遍历一下cnt数组,如果cnt[i][j]==X就说明是一个匹配点。
然后要判重,所以一次匹配成功可能会在多出++。具体就是开一个vector数组,保存所有k。然后迭代++就好了。
这个技巧真的很有趣,一方面多维护了一些信息就可以用一维的方法解决二维的问题,另一方面这种类似刷表法的思维有很多细节值得注意,而其应用也十分广泛。
代码
#include<bits/stdc++.h>
#define maxn 10010
#define sigmasize 26
using namespace std;
int ch[maxn][sigmasize];
int val[maxn],sz;
vector<int>vec[110];
void init()
{
memset(ch[0],0,sizeof(ch[0]));
val[0]=0;
sz=1;
}
int idx(char c)
{
return c-'a';
}
void insert(char* s,int v)
{
int l=strlen(s);
int j=0;
for(int i=0;i<l;i++)
{
int c=idx(s[i]);
if(!ch[j][c])
{
memset(ch[sz],0,sizeof(ch[sz]));
val[sz]=0;
ch[j][c]=sz++;
}
j=ch[j][c];
}
if(!val[j])
{
val[j]=v;
vec[v].clear();
vec[v].push_back(v-1);
}
else
{
vec[v]=vec[val[j]];
vec[v].push_back(v-1);
val[j]=v;
}
}
int f[maxn],last[maxn];
void getfail()
{
queue<int>q;
f[0]=last[0]=0;
for(int c=0;c<sigmasize;c++)
{
int u=ch[0][c];
if(!u) continue;
f[u]=last[u]=0;
q.push(u);
}
while(!q.empty())
{
int r=q.front();q.pop();
for(int c=0;c<sigmasize;c++)
{
int u=ch[r][c];
if(!u) {ch[r][c]=ch[f[r]][c];continue;}
q.push(u);
int v=f[r];
while(v&&!ch[v][c]) v=f[v];
f[u]=ch[v][c];
last[u]=val[f[u]]?f[u]:last[f[u]];
}
}
}
int N,M,X,Y;
char NM[1010][1010],XY[110][110];
int cnt[1010][1010];
void find(char* s,int I)
{
int l=strlen(s);
int j=0;
for(int i=0;i<l;i++)
{
int c=idx(s[i]);
j=ch[j][c];
if(val[j])
for(unsigned int k=0;k<vec[val[j]].size();k++)
{
int J=vec[val[j]][k];
if(I-J>=0) cnt[I-J][i-Y+1]++;
}
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
init();
scanf("%d %d",&N,&M);
for(int i=0;i<N;i++)
scanf("%s",NM[i]);
scanf("%d %d",&X,&Y);
for(int i=0;i<X;i++)
{
scanf("%s",XY[i]);
insert(XY[i],i+1);
}
getfail();
memset(cnt,0,sizeof(cnt));
for(int i=0;i<N;i++)
find(NM[i],i);
int CNT=0;
for(int i=0;i<N;i++)
for(int j=0;j<M;j++)
if(cnt[i][j]==X)
CNT++;
printf("%d\n",CNT);
}
return 0;
}
最后看看二维数组的状况就好了。
具体来讲,就是说如果在i行j列处完成了第k个字符串的匹配,那就在cnt[i-k][j-Y+1]处++。最后遍历一下cnt数组,如果cnt[i][j]==X就说明是一个匹配点。
然后要判重,所以一次匹配成功可能会在多出++。具体就是开一个vector数组,保存所有k。然后迭代++就好了。
这个技巧真的很有趣,一方面多维护了一些信息就可以用一维的方法解决二维的问题,另一方面这种类似刷表法的思维有很多细节值得注意,而其应用也十分广泛。
代码
#include<bits/stdc++.h>
#define maxn 10010
#define sigmasize 26
using namespace std;
int ch[maxn][sigmasize];
int val[maxn],sz;
vector<int>vec[110];
void init()
{
memset(ch[0],0,sizeof(ch[0]));
val[0]=0;
sz=1;
}
int idx(char c)
{
return c-'a';
}
void insert(char* s,int v)
{
int l=strlen(s);
int j=0;
for(int i=0;i<l;i++)
{
int c=idx(s[i]);
if(!ch[j][c])
{
memset(ch[sz],0,sizeof(ch[sz]));
val[sz]=0;
ch[j][c]=sz++;
}
j=ch[j][c];
}
if(!val[j])
{
val[j]=v;
vec[v].clear();
vec[v].push_back(v-1);
}
else
{
vec[v]=vec[val[j]];
vec[v].push_back(v-1);
val[j]=v;
}
}
int f[maxn],last[maxn];
void getfail()
{
queue<int>q;
f[0]=last[0]=0;
for(int c=0;c<sigmasize;c++)
{
int u=ch[0][c];
if(!u) continue;
f[u]=last[u]=0;
q.push(u);
}
while(!q.empty())
{
int r=q.front();q.pop();
for(int c=0;c<sigmasize;c++)
{
int u=ch[r][c];
if(!u) {ch[r][c]=ch[f[r]][c];continue;}
q.push(u);
int v=f[r];
while(v&&!ch[v][c]) v=f[v];
f[u]=ch[v][c];
last[u]=val[f[u]]?f[u]:last[f[u]];
}
}
}
int N,M,X,Y;
char NM[1010][1010],XY[110][110];
int cnt[1010][1010];
void find(char* s,int I)
{
int l=strlen(s);
int j=0;
for(int i=0;i<l;i++)
{
int c=idx(s[i]);
j=ch[j][c];
if(val[j])
for(unsigned int k=0;k<vec[val[j]].size();k++)
{
int J=vec[val[j]][k];
if(I-J>=0) cnt[I-J][i-Y+1]++;
}
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
init();
scanf("%d %d",&N,&M);
for(int i=0;i<N;i++)
scanf("%s",NM[i]);
scanf("%d %d",&X,&Y);
for(int i=0;i<X;i++)
{
scanf("%s",XY[i]);
insert(XY[i],i+1);
}
getfail();
memset(cnt,0,sizeof(cnt));
for(int i=0;i<N;i++)
find(NM[i],i);
int CNT=0;
for(int i=0;i<N;i++)
for(int j=0;j<M;j++)
if(cnt[i][j]==X)
CNT++;
printf("%d\n",CNT);
}
return 0;
}
相关文章推荐
- UVA 11019 Matrix Matcher 矩阵匹配器 AC自动机 二维文本串查找二维模式串
- uva11019 - Matrix Matcher 二维矩阵匹配 AC自动机
- uva 11019 - Matrix Matcher --AC自动机
- UVa11019 Matrix Matcher 留坑[AC自动机]
- 【ac自动机】uva11468 Substring && uva11019 Matrix Matcher
- AC自动机(二维) UVA 11019 Matrix Matcher
- 【Uva11019】Matrix Matcher【AC自动机】【二维字符串匹配】
- 矩阵匹配 AC自动机 或 二维Hash UVa 11019 - Matrix Matcher
- UVA 11019 Matrix Matcher(二维矩阵匹配ac自动机)
- UVA - 11019 Matrix Matcher (AC自动机(二维匹配) + dp)
- UVA 11019 Matrix Matcher( 二维字符匹配 AC自动机 + DP)
- UVa 11019 (AC自动机 二维模式串匹配) Matrix Matcher
- UVA 11019 Matrix Matcher——AC自动机
- UVA 11019 - Matrix Matcher(AC自动机 | hash大法)
- UVA 11019 Matrix Matcher(AC自动机)
- UVA-11019 - Matrix Matcher(AC自动机)
- UVA 11019 Matrix Matcher(AC自动机:矩阵匹配)
- UVA 11019 Matrix Matcher(字符串hash+KMP)
- AC自动机(矩阵匹配)uva11019
- UVA-11019Matrix Matcher(AC自动机)