KMP原始標準代碼

B - Number Sequence
Time Limit:5000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u

Description

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<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<vector>
#include<queue>
#include<stack>
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;

#define MaxSize 1000005
#define inf 0x3f3f3f3f
#define LL long long int

int n,m;
int ori[MaxSize],tar[MaxSize],NEXT[MaxSize];//有點醉,本來寫的next和algorithm庫裏面的東西重名CE了。所以用不着的頭文件別亂寫。

void get_NEXT()
{
  int i=0;//i是指在目標串中走到了i位
  int j=NEXT[0]=-1;//把這裏設置成-1,而不是0,是非常巧妙的。j一直都是NEXT[i]

  while(i<m)//得到目標串的NEXT,注意範圍
    {
      if(j==-1 || tar[j]==tar[i])//j==-1有兩種情況,第一個是剛開始從第0位開始的時候,第二個是後面找不到相同的前綴後一位的時候
        NEXT[++i] = ++j;

      else
        j=NEXT[j];

      /*如果一直這樣代換下去,走到j=0的時候,然後進行下一次循環:j==-1不滿足,
      於是就比較tar[0]和tar[i],就是a.....|b的第一位a和現在在i位上的b比較。
      如果j==0的時候tar[0]==tar[i]還不滿足,說明前面所有的前綴的之後一位都沒有和當前i位一樣的。
      那就應該有NEXT[++i]=0。在代碼中,如果j==0的時候tar[0]==tar[i]還不滿足,j就會走到-1,
      (因爲我們設置的NEXT[0]=-1)。於是下一步循環的時候,++j就就恰是0,於是NEXT[++i]=0,就是巧妙在這裏*/
    }
}

int match()
{
  int i=0;//i是指在原始串中走到了i位置
  int j=0;//j是指在目標串中走到了j位置

  while(i<n)//在原始串中從頭到尾匹配,如果走到最後,過程中都沒有return,說明沒有找到匹配。最後while結束後就返回-1
    {
      if(j==-1 || ori[i]==tar[j])//一位一位匹配下去
        {
          i ++;
          j ++;
        }

      else//走到某一位的時候發現不能匹配,那麼就移位。移位之後,j就跑到前綴的後一位,然後繼續往後匹配。當然此時的i是不應該變的。
        j=NEXT[j];
        /*如果j代換到了j==0,(原始串:....a.....,目標串b.....)那麼就是用當前原始串的第i位a比較目標串第一位b
        如果還不能匹配,那麼j就代換成-1,,原始串的i就到下一位,目標串的j本來是-1,加1之後就變成0,也就是又從第一位開始比較
        巧妙的=NEXT[0]=-1。*/

      if (j == m) return i-m+1;//匹配完了,j就會走到目標串的最後一位(即m-1位)之後,j++就變成了m,這裏就應該return了。
    }

  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",&ori[i]);

      for(int i=0; i<m; i++)
        scanf("%d",&tar[i]);

      get_NEXT();

      printf("%d\n",match());
    }

  return 0;
}//FROM CJZ


發佈了47 篇原創文章 · 獲贊 43 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章