zoukankan      html  css  js  c++  java
  • kmp

    kmp是一种在线性时间内能处理两个字符串的包含关系的算法,例如求一个字符串里有没有另一个字符串,一个字符串里有几个另一个字符串(可重叠和不可重叠两种)。

    贴个讲kmp的链接http://blog.csdn.net/yutianzuijin/article/details/11954939

    模板

    #include<stdio.h>
    #include<string.h>
    void makeNext(const char P[],int next[])
    {
        int q,k;
        int m = strlen(P);
        next[0] = 0;
        for (q = 1,k = 0; q < m; ++q)
        {
            while(k > 0 && P[q] != P[k])
                k = next[k-1];
            if (P[q] == P[k])
            {
                k++;
            }
            next[q] = k;
        }
    }
    
    int kmp(const char T[],const char P[],int next[])
    {
        int n,m;
        int i,q;
        n = strlen(T);
        m = strlen(P);
        makeNext(P,next);
        for (i = 0,q = 0; i < n; ++i)
        {
            while(q > 0 && P[q] != T[i])
                q = next[q-1];
            if (P[q] == T[i])
            {
                q++;
            }
            if (q == m)
            {
                printf("Pattern occurs with shift:%d
    ",(i-m+1));
            }
        }    
    }
    
    int main()
    {
        int i;
        int next[20]={0};
        char T[] = "ababxbababcadfdsss";
        char P[] = "abcdabd";
        printf("%s
    ",T);
        printf("%s
    ",P );
        // makeNext(P,next);
        kmp(T,P,next);
        for (i = 0; i < strlen(P); ++i)
        {
            printf("%d ",next[i]);
        }
        printf("
    ");
    
        return 0;
    }
    View Code

    poj1961

    题目大意,求这个字符串到i为止有多少个循环串;

    int k = i-next[i];
    if((i+1)%k == 0 && (i+1)!= k)
    printf("%d %d ", i+1, (i+1)/k);

    这是代码的主要部分,求next数组的部分大家都知道,我来说说这部分的正确性;

    例如一个字符串的第99为指向第96位,也就是说后4-99位和前1-96位是匹配的,就是说94到96与97到99是是匹配的;

    而且91-94与94-96是匹配的。。。。。。。。。。。

    一直可以推到最前面,以上就是正确性啦~

    代码

    #include <iostream>
    #include <string.h>
    #include <map>
    #include <stdio.h>
    using namespace std;
    const int maxa =1000005;
    int next[maxa];
    int vis[maxa];
    int n;
    void init_kmp(char str[])
    {
    memset(vis, 0, sizeof(vis));
    next[0]=-1;
    for(int i=1;str[i]!=0;i++)
    {
    int j= next[i-1];
    while(str[j+1]!=str[i]&&j>=0)
    j= next[j];
    if(str[j+1] == str[i])
    next[i] = j + 1;
    else
    next[i] = -1;
    }
    }
    int main(){
    char str[maxa];
    int d =1;
    while(scanf("%d", &n), n){
    scanf("%s", str);
    printf("Test case #%d
    ", d++);
    init_kmp(str);
    for(int i = 0; i < n; i++){
    int k = i-next[i];
    if((i+1)%k == 0 && (i+1)!= k)
    printf("%d %d
    ", i+1, (i+1)/k);
    }
    printf("
    ");
    }
    }
    View Code
  • 相关阅读:
    c/c++字符串传递
    从一个小程序明白new和delete的奇特现象
    Linux下构造函数string需要注意的问题
    字符串转time_t
    CentOS7基础建站指南(笔记)
    图与搜索
    面向的对象编程的小猫腻
    多线程编程
    生产者消费者模式-Java实现
    Java-代理模式的理解
  • 原文地址:https://www.cnblogs.com/icodefive/p/5176715.html
Copyright © 2011-2022 走看看