题解:KMP之Number Sequence

Given two sequences of numbers : a[1], a[2], … , a[N], and b[1], b[2], … , b[M] (1 <= M <= 10000, 1 <= N <= 1000000). Your task is to find a number K which make a[K] = b[1], a[K + 1] = b[2], … , a[K + M - 1] = b[M]. If there are more than one K exist, output the smallest one.
Input
The first line of input is a number T which indicate the number of cases. Each case contains three lines. The first line is two numbers N and M (1 <= M <= 10000, 1 <= N <= 1000000). The second line contains N integers which indicate a[1], a[2], … , a[N]. The third line contains M integers which indicate b[1], b[2], … , b[M]. All integers are in the range of [-1000000, 1000000].
Output
For each test case, you should output one line which only contain K described above. If no such K exists, output -1 instead.
Sample Input
2
13 5
1 2 1 2 3 1 2 3 1 3 2 1 2
1 2 3 1 3
13 5
1 2 1 2 3 1 2 3 1 3 2 1 2
1 2 3 2 1
Sample Output
6
-1

#include<cstring>
#include<cstdio>
#include<iostream>
using namespace std;
int a[1000010],b[10010],nex[10010],n,m;
void getnext()
{
 for(int i=1;i<m;i++)
 {
  int j=nex[i-1];
  while(b[j+1]!=b[i]&&j>=0)
   j=nex[j];
  if(b[j+1]==b[i]) 
   nex[i]=j+1;
  else 
   nex[i]=-1;
 }
 return;
}
void find()
{
 int i=0,j=0;
 while(i<n)
 {
  if(a[i]==b[j])
  {
  	i++;j++;
	if(j==m)
	{
	  cout<<i-m+1<<endl;
	  return ;
	}	
  }
  else
  {
  	if(j==0) i++;
  	else j=nex[j-1]+1;
  }
 }	
 cout<<"-1\n";
 return;
}
int main()
{
 int t;
 cin>>t;
 while(t--)
 {
  cin>>n>>m;
  for(int i=0;i<n;i++)
   cin>>a[i];
  for(int i=0;i<m;i++)	
   cin>>b[i];
  nex[0]=-1;
  getnext();
  find();
 }	
 return 0;
}
上一篇:9 进程管理


下一篇:HDU - 5955 Guessing the Dice Roll(AC自动机 高斯消元解dp方程)