【HDU-1686】Oulipo

92 阅读1分钟
题意

模式串在主串中出现了多少次。

 

样例
Sample Input
3
BAPC
BAPC
AZA
AZAZAZA
VERDI
AVERDXIVYERDIAN

Sample Output
1
3
0

 



 

AC代码
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;


char S[1000001];
char P[10001];

//int answer[100];

void GetNext(char* p,int* next)
{
	int pLen = strlen(p);
	next[0] = -1;
	int k = -1;
	int j = 0;
	while (j < pLen )   //这里从pLen-1变成pLen,作用是将next在最后面增加一位(对前几位没任何影响),在第一个结果出来后作j = next[j];,这个数组里的j就是增加得那一位得下标。这样可以使字串右移得位数变短,可以找出重叠的位置;如果不在next数组里增加那一位,则那一位就是定义数组时得默认初始值“0”,右移位数=j-0,就会右移过多,错过重叠的部分,
	{
		if (k == -1 || p[j] == p[k])
		{
			k++;
			j++;
			next[j] = k;
		}
		else
		{
			k = next[k];
		}
	}
/*
    cout<<"next数组1:";
    for(int i=0;i<pLen;i++)
        cout<<next[i]<<"  ";
    cout<<endl<<endl;
    */
}

int KmpSearch(char* s, char* p,int* next,int count)
{
    count=0;
	int i = 0;
	int j = 0;
	int sLen = strlen(s);
	int pLen = strlen(p);
	while (i < sLen && j < pLen)
	{
		if (j == -1 || s[i] == p[j])
		{
			i++;
			j++;
		}
		else
		{
			j = next[j];

		}
        if (j == pLen)
        {
            count++;
           // answer[++count]=i - j+1;
           // cout<<"第"<<count<<"个结果:"<<answer[count]<<"   "<<endl;

           //i=i-j+1   //这样说明又回到了暴力方法
            j = next[j];

	    }
	}
	return count;
}

int main()
{
    int next[10009];
    int count;
    int n;
    cin>>n;

    while(n--)
    {
         scanf("%s",P);
         scanf("%s",S);

         GetNext(P,next);
         cout<<KmpSearch(S,P,next,count)<<endl;

    }
    return 0;
}

 

题源:acm.hdu.edu.cn/showproblem…