题目:https://vjudge.net/problem/UVA-11019
题意:
给一个 n*m大矩阵,一个 x*y小矩阵;
求小矩阵在大矩阵中出现次数。
分析:
将小矩阵按行插入Trie树中;
结尾标记val为行号;
注意有可能多行对应一个节点,因此val应为vector;
find()大矩阵中每行,若出现匹配,则标记这次匹配对应的小矩阵右上角出现的位置;
若一个位置被标记次数>=x,则为一次成功匹配。
代码:
#include
using namespace std;
typedef long long ll;
const int tmax=1e4+5;
int n,m,x,y,num;
int ch[tmax*30][30],f[tmax*30],last[tmax*30],cnt[1005][1005];
char mat[1005][1005];
vector<int> val[tmax*30];
queue<int> Q;
void insert(char *s,int line)
{
int i,id,u=0,len=strlen(s);
for(i=0;i'a';
if(!ch[u][id]) ch[u][id]=++num;
u=ch[u][id];
}
val[u].push_back(line);
return;
}
void getfail()
{
int i,x,u,v;
Q.push(0);
while(!Q.empty())
{
x=Q.front();
Q.pop();
for(i=0;i<26;i++)
{
u=ch[x][i];
if(!u)
{
ch[x][i]=ch[f[x]][i];
continue;
}
Q.push(u);
if(x==0) continue;
v=f[x];
while(v&&!ch[v][i]) v=f[v];
f[u]=ch[v][i];
if(val[f[u]].size()==0) last[u]=last[f[u]];
else last[u]=f[u];
}
}
return;
}
void find(char *s,int line)
{
int i,u=0,j,k,len=strlen(s+1),id;
for(i=1;i<=len;i++)
{
id=s[i]-'a';
u=ch[u][id];
j=u;
do{
for(k=0;kif(line-val[j][k]+1>=1)
cnt[line-val[j][k]+1][i]++;
j=last[j];
}while(j);
}
return;
}
int main()
{
int T,i,j;
char tmp[105];
cin>>T;
while(T--)
{
for(i=1;i<=num;i++) val[i].clear();
num=0;
memset(ch,0,sizeof(ch));
memset(f,0,sizeof(f));
memset(last,0,sizeof(last));
memset(cnt,0,sizeof(cnt));
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
scanf("%s",&mat[i][1]);
scanf("%d%d",&x,&y);
for(i=1;i<=x;i++)
{
scanf("%s",tmp);
insert(tmp,i);
}
getfail();
for(i=1;i<=n;i++)
find(mat[i],i);
int ans=0;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
if(cnt[i][j]>=x) ans++;
printf("%d\n",ans);
}
return 0;
}