poj 3461 && hdu 1686 Oulipo (kmp)


タイトルリンク:http://poj.org/problem?id=3461
 
問題解決レポート:文字列マッチングの鍵はnext配列が理解しにくいことです.
 
参考資料には
(1)next[0]=−1の意味:任意の列の最初の文字のモード値は−1とする.
(2)next[j]=-1の意味:パターン列Tにjと表記された文字が、先頭文字と
同じで、jの前の1-k文字と先頭の1-k文字
個の文字は等しくない(または等しいがT[k]==T[j])(1≦k例えば、T="abCabCad"ならnext[6]=-1、T[3]=T[6]
(3)next[j]=k意味:パターン列Tにjと表記された文字が、jの前にk個ある場合
文字は先頭のk文字と等しく、T[j]!=T[k] (1≤kすなわちT[0]T[1]T[2].T[k-1]==
T[j-k]T[j-k+1]T[j-k+2]…T[j-1]
そしてT[j]!=T[k].(1≤k(4)next[j]=0の意味:(1)(2)(3)を除く場合.
 
 
next配列の意味:
1.next[n]=  -1はA[m]とB[0]が間接的に比較したことを表して、等しくなくて、次の比較 A[m+1]とB[0]
2.next[n]=0は比較中に不等が生じたことを示し、次の比較 A[m]とB[0].
3.next[n]=k>0しかしknext配列の求め方については、http://www.cppblog.com/oosky/archive/2006/07/06/9486.htmlを参照してください.     
 
#include<cstdio>
#include<cstring>
using namespace std;

const int max1 = 10000 + 5;
const int max2 = 1000000 + 5;
int next[max1], len1, len2;

void get_next(char a[])
{
	int i,j=-1;
	memset(next,0,sizeof(next));
	next[0]=-1;
	for(i=1;i<=len1;i++)
	{
		while(j>-1&&a[j+1]!=a[i])
			j=next[j];
		if(a[j+1]==a[i]) 
			j++;
		next[i]=j;
	}
}

int KMP(char a[],char b[])
{
	get_next(a);
	int i,j=-1,cnt=0;
	for(i=0;i<len2;i++)
	{
		while(j!=-1&&a[j+1]!=b[i])
			j=next[j];
		if(a[j+1]==b[i])
			j++;
		if(j==len1-1)
			cnt++;	
	}
	return cnt;
}

int main() 
{
	char w[max1],t[max2];
	int n,ans;
	scanf( "%d",&n );
	while( n-- )
	{
		len1=len2=0;
		scanf("%s %s",w,t);
		for(int i=0;w[i]!='\0';i++) len1++; 
		for(int j=0;t[j]!='\0';j++) len2++;
		int ans = KMP(w,t);
		printf("%d
",ans); } return 0; }

 
                                                                       
 
 
 
4.