首页 > 代码库 > Hdu 1686 Oulipo

Hdu 1686 Oulipo

Problem地址:http://acm.hdu.edu.cn/showproblem.php?pid=1686

 

字符串匹配,因此采用了KMP算法。有一点需要注意,请看题目的样例2:

T:  AZA

S:  AZAZAZ

很明显T和S的前3位匹配,那么接下来呢?

我最初设计的程序,T和S的前三位匹配后,T开始与S的第四位进行匹配判断。

但实际上,S的第三位至S的第五位可以与T匹配。

 

为什么会这样呢?

我思考了之后明白了问题所在:当T在S中找到一个匹配串后,T将第一位与S的下一位进行比较。这实际上可能造成失去发现一个新字符串匹配的机会。

因此,当T在S中找到一个匹配串后,T不应将第一位与S的下一位进行比较。那应该将T的第几位比呢?其实思考一下就可以知道怎么办。

将T与自己匹配,当比较结束后,看一下作为待匹配的T最多与模式串T的第几位匹配即可。

 

 

#include <iostream>#include <cstring>#include <cstdio>using namespace std;const int W_MAXN = 10000 + 50;char word[ W_MAXN ];int next[ W_MAXN ];const int T_MAXN = 1000000 + 50;char text[ T_MAXN ];int End;void Get_next()   //  得到next数组{	int i, j = 0;	next[ 1 ] = 0;	int length = strlen( word+1 );	for( i=2;i<=length;i++ )	{		next[i] = j;		if( word[i]!=word[ j+1 ] )		{		    	j = next[ j+1 ];		}		else		{		    	j ++;		}	}}void Get_End(){	int i, j = 0;   	int finish = strlen ( word+1 );	for( i=2; i<=finish;i++ )	{		while( j>0 && word[i]!=word[j+1] )		{			j = next[ j+1 ];		}		if( word[i]==word[j+1] )		{			j ++;		}	}	End = j;}int Count(){    int counter = 0;    int i, j = 0;    int finish = strlen ( word+1 );    int length = strlen ( text+1 );    for( i=1;i<=length;i++ )    {        while( j>0 && text[i]!=word[ j+1 ] )        {            j = next[ j+1 ];        }        if( text[i] == word[j+1] )        {            j ++;        }        if( j==finish )        {            j = End;  // 不应 j = 0            counter ++;        }    }    return counter;}int main(){    int T;    scanf( "%d", &T );    while( T-- )    {        scanf( "%s", word+1 );        scanf( "%s", text+1 ); // 为方便, 均从第一位读起        Get_next();        Get_End();        printf( "%d\n", Count() );    }    return 0;}

 

Hdu 1686 Oulipo