KMP

View Code
const int maxn = 11111; //文本最大长度
int fail[maxn];    //失败了应该跳的位置
char str[maxn], text[maxn];  //输入文本和待匹配的字符串
//初始位置从0开始
void get_next(int n) {
    int i, j=-1;
    for(fail[0]=-1, i=1;i < n; i++) {
        while(j>=0 && str[i]!=str[j+1])  j=fail[j];
        if(str[j+1]==str[i])  j++;  
        fail[i]=j;
    }
}

int kmp(int n,int m) { //n:str长度 m:text长度
    int i, j=-1, count=0;
    get_next(n);
    for(i = 0;i < n; i++) {
        while(j>=0 && text[i]!=str[j+1])  j=fail[j];
        if(text[i]==str[j+1])   j++;
        if(j==m-1) {
            count++;
            //      printf("%d\n", i-m+2);  //存在的话打印输出匹配的开始位置
            j = fail[j];   //保证程序继续进行
        }
    }
    return count;
}

 kmp求一个字符串循环,if(n%(n-1-fail[n-1])==0) ans=n/(n-1-fail[n-1]);

View Code
//kmp求一个字符串循环,if(n%(n-1-fail[n-1])==0) ans=n/(n-1-fail[n-1]);
/*****************************\
必要性:存在最小循环节长度为k,有fail[n-1]=n-1-k;所以n%(n-1-fail[n-1])=0
\*****************************/
const int MM = 1111111;
typedef __int64 int64;
#define debug puts("wrong")
int n;
int fail[MM];
char str[MM];

void get_next(int n) {
    int i,j=-1;
    for(fail[0]=-1,i=1;i<n;i++) {
        while(j>=0 && str[i]!=str[j+1]) j=fail[j];
        if(str[j+1]==str[i]) j++;
        fail[i]=j;
    }
}
void get_data() { 
    int i,j,k;
//    scanf("%s", str);
    n=strlen(str);
    get_next(n);
}

void solve() {
    int i,j,k,ans=1, tmp=n-fail[n-1]-1;
    if(n%tmp==0) printf("%d\n",n/tmp);
    else printf("1\n");
}

int main() {
    while(scanf("%s",str)!=EOF) {
        if(str[0]=='.') break;
        else get_data(),solve();
    }
    return 0;
}

拓展KMP

http://poj.org/problem?id=2752 

View Code
//POJ2752 输出一个字符串的所有后缀与此字符串前缀完全匹配的长度 
const int MM = 1111111;
typedef __int64 int64;
#define debug puts("wrong")
int N,M;
int fail[MM];
int next[MM], cnt, res[MM];
char str[MM], ch[MM];
/**************************************\
next[i]存的是str[i]的后缀suf[i]与ch的前缀
的最大匹配字符的个数 复杂度:O(N)
\**************************************/
void get_extend_next(int n) {
    int i,j=0,k,len,l;
    while((j+1)<n && str[j]==str[j+1]) j++;
    fail[1]=j;
    for(k=1,i=2; i<n ;i++) {
        len=k+fail[k]-1, l=fail[i-k];
        if(l<(len-i+1)) fail[i]=l;
        else {
            j=f_max(0,len-i+1);
            while((i+j)<n && str[i+j]==str[j]) j++;
            fail[i]=j, k=i;
        }
    }
}

void extend_kmp(int n,int m) { //n为模式串的长度 m为匹配串的长度
    int i,j=0,k,len,l;
    while(j<n && j<m && ch[j]==str[j]) j++;
    next[0]=j;
    for(k=0,i=1; i<m ;i++) {
        len=k+next[k]-1,l=fail[i-k];
        if(l<(len-i+1)) next[i]=l;
        else {
            j=f_max(0,len-i+1);
            while((i+j)<m && j<n && str[j]==ch[i+j]) j++;
            next[i]=j, k=i;
        }
    }
}

void solve() {
    int i,j,k,n,m;
    n=strlen(str);
    for(i=0;i<n;i++) ch[i]=str[i]; ch[n]='\0';
    m=strlen(ch);
    get_extend_next(n);
    extend_kmp(n,m);
    cnt=0;
    for(i=n-1;i>=0;i--) if((n-i)==next[i]) res[cnt++]=n-i;
    printf("%d",res[0]); for(i=1;i<cnt;i++) printf(" %d",res[i]); printf("\n");
}

int main() {
    while(scanf("%s",str)!=EOF) solve();
    return 0;
}
原文地址:https://www.cnblogs.com/zhang1107/p/3030967.html