xws117的专栏

新浪微博: http://weibo.com/2139773423/

HDU 3336 一个next数组就解决了

这道题本来是用来练习KMP的  

结果貌似一个next数组就可以解决 

首先 对于每一个元字符串的前缀数组来说   至少会有一个与他匹配的 (其实就是他本身)


那么 再看看next数组的含义  每一个不为0的next数就代表着有一个子串重复过一次 比如abab   的next数组为0001 

b所在的1  就代表着长度为1 的原字符串的前缀数组重复过一个   即a重复了一次   这时  我们会发现    ab也重复过一次  那么这一次与去哪了呢?   这时  我们需要在abab的后面加一个不相干的字符 ‘ * ’,  这样 abab*  的next数组就变成了

00012   这样ab的重复的次数就出现了   在我们之后的统计的过程中 我们可以让所有在next数组中大于0的数使sum++;

然后再让sum+strlen(字符串)   就可以得出总的重复数了  别忘了模上10007

下面是AC 代码

# include <stdio.h>
# include <string.h>
char s[200000+10];
//char p[200000+10];
int sum;
int f[200000+10];
void next(int x){
    f[0]=f[1]=0;
    for(int i=1;i<x-1;i++){
        int j = f[i];
        while(j&&s[i]!=s[j]) j=f[j];
        f[i+1] = s[i]==s[j]?j+1:0;
    }
}
void solve(int x){
    for(int i=0;i<x;i++){;
        if(f[i]>0)
            sum+=1;
        //printf("%d    \n",f[i]);
    }
}
int main(){
    int T;
    while(scanf("%d",&T)!=EOF){
        int len;
        memset(f,0,sizeof(f));
        scanf("%d",&len);
        scanf("%s",s);
        sum=0;
        s[len]='*';
        s[len+1]='\0';
        next(len+1);
        solve(len+1);
        printf("%d\n",(sum+len)%10007);
    }
    return 0;
}


阅读更多
个人分类: 面试 hdu kmp
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭