zoukankan      html  css  js  c++  java
  • poj 3080 get_next + kmp + 字符数组做函数参数 + 数组下标从1 开始

    题目来源:

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

    分析:

    题意要求你求出每组字符串的最长公共子串,公共子串长度要求至少为3。

    注意,当出现等长的公共字符串时,输出按字典序字符串最小的那个。若没公共子串,输出“no significant commonalities。

    分析: 用kmp 枚举,让第一个字符串的长度大于等于3的子串分别与其他字符串匹配比较,第一个字符串的长度 从 len 开始向下减, 直到发现一个 公共字串,则为最大 公共字串。

    代码如下:

    const int Max_N = 65;
    char s[12][Max_N];
    int next[Max_N];
    //后缀数组(前缀函数)
    //数组从1开始
    void get_next(int m, char * p){
        char tmp[Max_N];
        strcpy(tmp+1, p);
        int i,k=0;
        next[1]=0;
        for(i=2; i<=m ; i++){
            while(k>0 && tmp[k+1] != tmp[i])
                k=next[k];
            if(tmp[k+1] == tmp[i])
                k++;
            next[i]= k;
        }
    }
    // 匹配算法,t1为目标串,n为目标长度, p1为模式串, m为 模式长度
    // 下标都从1开始
    bool kmp(char * t1, char * p1,int n, int m){
        char t[Max_N], p[Max_N];
        strcpy(t+1,t1);
        strcpy(p+1,p1);
        int i,k=0;
        int cnt=0;
        for(i=1; i<=n; i++){
            while(k>0 && p[k+1] != t[i])
                k=next[k];
            if(p[k+1] == t[i])
                k++;
            if(k == m)
                return 1;
        }
        return 0;
    }
    int main(){
        int t,j;
        scanf("%d",&t);
        while(t--){
            int m;
            int flag = 0;
            char res[Max_N] = "no significant commonalities";
            scanf("%d",&m);
            for(int i=0; i<m; i++)
                scanf("%s",s[i]);
            int len=strlen(s[0]);
            for(int l=len ; l>=3; l--){ // 枚举子串的长度从大到小
                for(int pos = 0; pos + l <= len ; pos++){ // 枚举第一个字符串的位置从0到最大
                    get_next(l, s[0]+pos );
                    for( j=1; j<m; j++){
                        int n=strlen(s[j]);
                        if( !kmp(s[j] , s[0]+ pos, n,l) )
                            break;
                    }
                    if(j == m ){
                        if(strcmp(res, s[0]+pos) > 0){ // 若长度相等,但从不同位置开始的,还需比较字典序最小
                            strcpy(res , s[0]+pos );
                            res[l] = '';   //使复制的到 l-1 处结束输出 ,这个地方 很关键
                            flag=1;
                        }
                    }
                }
                if(flag)
                    break;
            }
            printf("%s
    ",res);
        }
        return 0;
    }
  • 相关阅读:
    Collections和Arrays常用方法
    集合(三)------双列集合
    集合(二)------单列集合
    集合(一)----------概述
    泛型
    线程
    Math类和Random类(数学公式相关类)
    时间相关的类
    Runtime类及其常用方法
    第65题:有效数字
  • 原文地址:https://www.cnblogs.com/zn505119020/p/3676887.html
Copyright © 2011-2022 走看看