Cow Patterns
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 4184 | Accepted: 1496 |
Sample Input
9 6 10 5 6 2 10 10 7 3 2 9 1 4 4 3 2 1
Sample Output
1 3
题目大意:给定数串A(母串),数串B(子串),在A中寻找与B串符合特性匹配的开始位置,并输出个数与位置,
例如:模式串1 4 4 2 3 1,主串5 6 2 10 10 7 3 2 9
那么2 10 10 7 3 2 就是匹配的。
问题分析:匹配特性:若当前位置匹配,则需满足 之前1-比当前数小 2-比当前数相等 的数的个数相等 ,
根据特性得到模式串的next数组,后对主串进行匹配,可用KMP算法实现。
CODE:
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <vector>
#define MAXN 100005
#define MAXM 25005
using namespace std;
int n,m,s,sum;
int a[MAXN],b[MAXM],ans[MAXN];
int as[MAXN][27],bs[MAXM][27];
int next[MAXM];
void init()
{
for(int j=1; j<=25; ++j)
{
as[0][j]=0;
bs[0][j]=0;
}
bs[0][b[0]]++;
as[0][a[0]]++;
for(int i=1; i<n; ++i)
{
for(int j=1; j<=25; ++j)
as[i][j]=as[i-1][j];
as[i][a[i]]++;
}
for(int i=1; i<m; ++i)
{
for(int j=1; j<=25; ++j)
bs[i][j]=bs[i-1][j];
bs[i][b[i]]++;
}
}
void kmp()
{
int i,j,x,xx,y,yy;
next[0]=j=-1;
i=0;
while(i<m)
{
x=xx=y=yy=0;
if(j>-1)
{
for(int k=1; k<b[i]; ++k)
x+=bs[i][k]-bs[i-j-1][k];
for(int k=1; k<b[j]; ++k)
y+=bs[j][k];
xx=bs[i][b[i]]-bs[i-j-1][b[i]];
yy=bs[j][b[j]];
}
if(j==-1 ||(x==y&&xx==yy))
next[++i]=++j;
else j=next[j];
}
}
void kmp_per()
{
int i,j,x,xx,y,yy;
i=j=0;
while(i<n)
{
x=xx=y=yy=0;
if(j!=-1)
{
for(int k=1; k<a[i]; ++k)
{
if(i>j)
x+=as[i][k]-as[i-j-1][k];
else x+=as[i][k];
}
for(int k=1; k<b[j]; ++k)
y+=bs[j][k];
if(i>j)
xx=as[i][a[i]]-as[i-j-1][a[i]];
else xx=as[i][a[i]];
yy=bs[j][b[j]];
}
if(j==-1 || (x==y&&xx==yy))
{
++i;
++j;
if(j>=m)
{
ans[sum++]=i-m+1;
j=next[j];
}
}
else j=next[j];
}
}
int main()
{
while(scanf("%d%d%d",&n,&m,&s)!=EOF)
{
for(int i=0; i<n; ++i)
scanf("%d",a+i);
for(int i=0; i<m; ++i)
scanf("%d",b+i);
sum=0;
init();
kmp();
kmp_per();
printf("%d\n",sum);
for(int i=0; i<sum; ++i)
printf("%d\n",ans[i]);
}
return 0;
}