您的位置:首页 > 其它

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: