题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1711
解题报告:一道比较简单的kmp题目,还是很佩服当初发明者个算法的一群人,怎么想到的next数组的写法,让我们这帮菜鸟反复理解其含义。不知道为什么这么写,但我们至少要理解next的含义。
首先:next[0]=-1 ,是我们规定的每个串的第一个值为-1;
其次: next[j]=-1,这儿有两种可能。
第一,第j个元素的值和第一个元素的值相等 且 J前面的k个元素与前1~k个元素不相等。
第二,前面的1~k个元素与j前面的k个元素相等,但是next[j]==next[k]。
如abcabcad中next[6]=-1,因为a[3]=a[6] ;
再次:next[j]=k的情况。前面的1~k个元素与j前面的k个元素相等,但是next[j]!=next[k]。
最后:next[j]=0:除了上述的三种情况。
#include<cstdio>
#include<cstring>
using namespace std;
const int MAX2 = 10000+5;
const int MAX1 = 1000000+5;
int n,m;
int next[MAX2],b[MAX2],a[MAX1];
void get_next()
{
int j=-1,i;
next[0]=-1;
for(int i=1;i<=m;i++)
{
while(j>-1&&b[j+1]!=b[i])
{
j=next[j];
}
if(b[j+1]==b[i])
j++;
next[i]=j;
}
}
int KMP()
{
get_next();
int j=-1,cnt=0,i,pos=0;
for(int i=0;i<n;i++)
{
while(j>-1&&b[j+1]!=a[i])
{
j=next[j];
}
if(b[j+1]==a[i])
j++;
if(j==m-1)
{
pos=i;
cnt=j;
break;
}
}
if(pos != 0) return pos-cnt+1;
return -1;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d %d",&n,&m);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
for(int j=0;j<m;j++)
scanf("%d",&b[j]);
int ans = KMP();
printf("%d\n",ans);
}
return 0;
}