• 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;
    }
  • 相关阅读:
    js扩展Date对象的方法,格式化日期格式(prototype)
    JSP中的普通路径写法
    工作方向与目标
    Cookie工具类(获取cookie,设置cookie)
    读取普通java web项目下的WEB-INF目录下的配置文件(application.xml,xx.properties等配置文件)
    js单选和全选
    exits 和no exits
    Linux配置nginux
    Java读取利用java.util类Properties读取resource下的properties属性文件
    vue-devtools vue调试工具
  • 原文地址:https://www.cnblogs.com/zhang1107/p/3030967.html
Copyright © 2020-2023  润新知