Hdu 1686 Oulipo

本文深入探讨了KMP算法在解决字符串匹配问题中的应用,并通过实例解析了算法实现过程中容易忽视的关键细节。重点阐述了如何正确处理匹配串与模式串之间的比较,避免了可能的匹配误判,提高了算法的效率与准确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

 

转载于:https://www.cnblogs.com/Emerald/p/4156120.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值