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;
}

 

posted @ 2014-12-10 19:02  Emerald  阅读(314)  评论(0编辑  收藏  举报