poj 2406 Power Strings(kmp求一个串的重复子串)

题意:重复子串次数

思路:kmp

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;

#define MaxSize 1000005

int next[MaxSize];

void GetNext(char t[]){//求next数组
    int j,k,len;
    j=0;
    k=-1;
    next[0]=-1;
    len=strlen(t);
    while(j<len){
        if(k==-1||t[j]==t[k]){
            ++j;
            ++k;
            next[j]=k;//此句可由优化替代
            /*优化(仅保证求KMPIndex时可用。谨慎使用。)
            if(t[j]!=t[k])next[j]=k;
            else next[j]=next[k];
            */
        }
        else k=next[k];
    }
}

int KMPIndex(char s[],char t[]){//求子串首次出现在主串中的位置
    int i,j,lens,lent;
    i=j=0;
    lens=strlen(s);
    lent=strlen(t);

    while(i<lens&&j<lent){
        if(j==-1||s[i]==t[j]){
            ++i;
            ++j;
        }
        else j=next[j];
    }
    if(j>=lent)return i-lent;
    else return -1;
}

int KMPCount(char s[],char t[]){//统计子串在主串中的出现次数,可重叠
    int i,j,lens,lent,cnt;
    i=j=0;
    lens=strlen(s);
    lent=strlen(t);
    cnt=0;

    while(i<lens){
        if(j==-1||s[i]==t[j]){
            ++i;
            ++j;
        }
        else j=next[j];
        if(j==lent)++cnt;
    }
    return cnt;
}

void KMPCount2(char t[]){//统计单串中从某个位置以前有多少重复的串
    int i,lent,tmp;
    lent=strlen(t);

    for(i=2;i<=lent;++i){
        tmp=i-next[i];
        if(i%tmp==0&&i/tmp>1)
            printf("\t位置:%d 个数:%d\n",i,i/tmp);
    }
}

int main(){
    char str[MaxSize];
    int len;
    while(~scanf("%s",str)&&str[0]!='.'){
        GetNext(str);
        len=strlen(str);
        if(len%(len-next[len])==0&&len/(len-next[len])>1)printf("%d\n",len/(len-next[len]));
        else printf("1\n");
    }
    return 0;
}
View Code

 

posted @ 2015-08-20 21:00  gongpixin  阅读(291)  评论(0编辑  收藏  举报