hdu 3336 kmp

这道题要求的是所有类型前缀的与整个字符串匹配出的个数之和

那么所以每个可以先从头开始,把每个前缀先算进去,然后利用next数组的性质,也就是当前pre[i-1]==suffix[i-k]

所以我们可以对应每个i找到从它开始的最大的串和一个前缀完全匹配

那么i就可以贡献出这个前缀长度的个数,因为前缀中从[1-len]都可以匹配到一个新的串

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define MAX 200007
#define MOD 10007

using namespace std;

void get_next ( char p[] , int next[] )
{
    int i = 0 , k = -1 , len = strlen(p);
    next[0] = -1;
    while ( i < len )
        if ( k == -1 || p[i] == p[k] )
           i++,k++,next[i] = k;
        else k = next[k]; 
}

int pre[MAX];
int sum[MAX];

int solve ( char s[] , int n )
{
    int next[MAX];
    get_next ( s , next );
    /*cout << "_________next__________________" << endl;
    for ( int i = 0 ; i <= n ; i++ )
        cout << next[i] << " " ;
    cout << endl;
    cout << "_______________________________" << endl;*/
    memset ( pre , 0 , sizeof ( pre ) );
    memset ( sum , 0 , sizeof ( sum ) );
    for ( int i = 1 ; i <= n ; i++ )
        pre[i-next[i]] = max ( next[i] , pre[i-next[i]] );
    /*cout << "_________pre____________________" << endl;
    for ( int i = 0 ; i <= n ; i++ )
        cout << pre[i] << endl;
    cout << "________________________________" << endl;*/
    int ans = n;
    for ( int i = 1 ; i < n ; i++ )
        ans = ( ans + pre[i] )%MOD;
    return ans;
}

int t,n;
char s[MAX];

int main ( )
{
    scanf ( "%d" , &t );
    while ( t-- )
    {
        scanf ( "%d" , &n );
        scanf ( "%s" , s );
        printf ( "%d\n" , solve ( s , n ) );
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值