您的位置:首页 > 其它

HDU3336 KMP之next数组妙用

2013-11-01 19:35 197 查看
本题要求所给字符串的前缀在整个字符串中出现的次数的累加和。KMP算法的运用。
容易联想到KMP算法中的next[]数组,当next[i]>0时可以理解为i前面的next[]个字符组成的字符串对应一个前缀。此外长度为n的字符串有n个前缀。
所以res等于n加上所有next值大于0的元素的个数。
例如:abab

那么他的前缀有a , ab ,aba , abab。

对应的在原串中的个数为a有2个,ab有2个,aba有1个,abab有1个。

那么总数是6。

思路:对这个字符串求出Next数组,那么对于每个Next[i] = k ,那么我们就知道前缀0 -> k - 1处有一个匹配。那么累加即可。

那么只需根据Next数组匹配成功的个数进行累加即可。


/**********************

* author:crazy_石头

* Pro:HDOJ 3336

* algorithm: KMP

* Judge Status:Accepted

* Memory:1246K

* Time:46ms

* date:2013/11/01

***********************/

#include <iostream>

#include <cstdlib>

#include <cstdio>

#include <cstring>

using
namespace std;

#define rep(i,h,n) for(int i=(h);i<=(n);i++)

const int maxn=200000+5;

int next[maxn];

char p[maxn];

int n,test;//主串的串长;

inline
void getNext(char *p,int *next)

{

int i,j,m;

i=0,j=-1;

next[0]=-1;

m=strlen(p);

while(i<m)

{

if(j==-1||p[i]==p[j])

i++,j++,next[i]=j;

else

j=next[j];

}

}

int main()

{

scanf("%d",&test);

while(test--)

{

scanf("%d",&n);

scanf("%s",p);

getNext(p,next);

int res=n;

rep(i,0,n)

{

if(next[i]>0)

res=(res+1)%10007;

}

printf("%d\n",res);

}

return
0;

}

* This source code was highlighted byYcdoiT.
( style: Friend )
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: