Hdu 3336 Count the string[KMP next数组的理解]

题意:求字串中【前缀+跟前缀相同的子串】的个数?

Sample Input
1
4
abab

Sample Output
6

abab:包括2个a,2个ab,1个aba,1个abab


这里要用到next值的意义:
next[i]表示前i个字符所组成的字符串最大前后缀匹配长度
举个例子:

next[5]=2, 表示下标5前面那个字符串abcab的前后缀匹配的最大长度是2,显然就是ab了

回到本题:
所求=字串的前缀个数+与前缀相同的子串
问题可以部分转化为:每个前缀的最大前后缀匹配问题

继续用上面的例子:

第一步:

对于这段子串,next[5]=2,然后后面不符合next值的递增规律了。
所以对于abcab,长度为2的后缀,即ab与前缀匹配
所以+1个ab,注意还要+1个a,既然后缀ab跟前缀ab匹配,则必有a跟前缀匹配。
也就是+2个了,其实实际上+next[5]就可以了,因为这是最长前后缀匹配长度

第二步:

对于这段子串:
next[6]=1,然后后面不符合next值的递增规律了。
所以对于abcaba,长度为1的后缀,即a与前缀匹配。
所以+1个a,也就是+next[6]了。

第三步:

对于整个串:
next[12]=4后面没有了
所以对于整个串:abcabacbabca,长度为4的后缀跟前缀匹配
所以+1个abca,+1个abc,+1个ab,+1个a,总共+4个,也就是+next[12]了

最后:
好了,刚刚一共+了7个与前缀匹配的子串
上面说了题目是求:字串的前缀个数+与前缀相同的子串个数
与前缀相同的子串个数就是7个了
然后字串的前缀个数当然就是整个串的长度了,那么就是12个

加起来就是答案:19。

到这里,有些同学就要问了,为什么next[4]为什么就不做处理了呢??

我一开始也是这么想的,为什么呢??

因为,next[4]的后面的next[5]==(正好)next[4]+1。这不是偶然,因为abca的最大后缀为1(a),而abcab的最大后缀为2(ab),这里的ab包含了前面的a。所以,如果正好next[i]+1=next[i]的话,前面的被后面包含了。

代码:

#include 
#include 
#include 
#include 
using namespace std;

const int N=200003;
char Str[N];
int n,next[N];

void Get_Next(){
    next[0]=-1;
    int j=-1,i=0;
    while(i0&&next[i]+1!=next[i+1])
            ans=(ans+next[i])%10007;
        }
        printf("%d\n",ans);
    }
    return 0;
}

由此可见,KMP的next数组的博大精深呐!!

你可能感兴趣的:(Hdu 3336 Count the string[KMP next数组的理解])