zoukankan      html  css  js  c++  java
  • 字符串截取模板 && POJ 3450、3080 ( 暴力枚举子串 && KMP匹配 )

    //截取字符串 ch 的 st~en 这一段子串返回子串的首地址
    //注意用完需要根据需要最后free()掉
    
    char* substring(char* ch,int st,int en)
    {
        int length = en - st + 1;
        char* pch=ch;
        char* subch=(char*)malloc(length+1);
        pch=pch+st;
        for(int i=0;i<length;i++)   subch[i]=*(pch++);
        subch[length]='';
        return subch;
    }
    字符串截取

    POJ 3080 Blue Jeans

    题意 : 给出 n 个包含 60 个字符的字符串,问你这 n 个字符串的最长公共子串是什么,如果有多个,输出字典序最小的,如若没有则输出 “no significant commonalities”

    分析 : 直接选择第一个串然后从长到短截取各个长度的子串去跟剩下的 n-1 个串进行匹配,如果得以匹配则比较这个长度下的其他未枚举的子串,选出字典序最小的继续匹配,持续更新答案,最后输出即可。

    #include<string.h>
    #include<stdio.h>
    #include<string>
    #include<malloc.h>
    #include<stdlib.h>
    using namespace std;
    const int maxn = 60 + 5;
    char str[10][maxn], fir[maxn];
    char * mo, * ans;
    int num, Next[maxn], moL;
    char* substring(char* ch,int st,int en)
    {
        int length = en - st + 1;
        char* pch=ch;
        char* subch=(char*)malloc(length+1);
        pch=pch+st;
        for(int i=0;i<length;i++)   subch[i]=*(pch++);
        subch[length]='';
        return subch;
    }
    inline void GetNext()
    {
        int i = 0, j = -1;
        Next[i] = j;
        while(i < moL){
            while(j!=-1 && mo[i]!=mo[j]) j = Next[j];
            Next[++i] = ++j;
        }
    }
    bool KmpCount(int who)
    {
        int i = 0, j = 0;
        while(j < moL && i < 60){
            while(j!=-1 && mo[j]!=str[who][i]) j = Next[j];
            i++, j++;
        }
        if(j == moL) return true;
        return false;
    }
    bool Is_Match(int st, int en)
    {
        moL = en - st + 1;
        mo = substring(fir, st, en);
        GetNext();
        for(int k=1; k<num; k++){
            if(!KmpCount(k))
                return false;
        }return true;
    }
    inline void Find_better_ans(int pos, int len, int en)
    {
        for(int i=pos+1; i<=en; i++){
            for(int k=0,j=i; j<=i+len; j++,k++){
                if(ans[k] > fir[j]){
                    if(Is_Match(i, i+len)){
                        ans = substring(mo, 0, moL-1);
                    }else { free(mo); break; }
                }else if(ans[k] < fir[j]) break;
            }
        }
    }
    bool Have_ans()
    {
        for(int len=59; len>=1; len--){///枚举截取子串的长度,从大到小枚举
            for(int i=0; i<=59-len; i++){///在这个长度下,枚举所有子串的首字母
                if(Is_Match(i, i+len)){///判断是否匹配
                    ans = substring(mo, 0, moL-1);
                    Find_better_ans(i, len, 59-len);
                    return true;
                }else free(mo);
            }
        }return false;
    }
    int main(void)
    {
        int nCase;
        scanf("%d", &nCase);
        while(nCase--){
            scanf("%d", &num);
            scanf("%s", fir);
            for(int i=1; i<num; i++) scanf("%s", str[i]);
            if(Have_ans()) { puts(ans); free(ans); }
            else puts("no significant commonalities");
        }
        return 0;
    }
    View Code

    POJ 3450 Corporate Identity

    题意 : 给出 n 个字符串,问你最长的公共子串,没有则输出 “IDENTITY LOST”

    分析 : 这次直接选一个最短的,枚举其所有的子串去匹配剩下的 n-1 个串即可

    #include<stdio.h>
    #include<string.h>
    #include<malloc.h>
    #include<algorithm>
    const int maxn = 4050;
    char StrGroup[maxn][maxn], str[maxn], *mo, *ans;
    int moL, Next[maxn], num, MinL, index, Len[maxn];
    char* substring(int st,int en)
    {
        int length = en - st + 1;
        char* subch=(char*)malloc(length+1);
        for(int i=0,j=st;i<length;j++,i++)   subch[i]=StrGroup[index][j];
        subch[length]='';
        return subch;
    }
    inline void GetNext()
    {
        int i = 0, j = -1;
        Next[i] = j;
        while(i < moL){
            while(j!=-1 && mo[i]!=mo[j]) j = Next[j];
            Next[++i] = ++j;
        }
    }
    bool RunKmp(int who)
    {
        int i = 0, j = 0;
        while(j < moL && i < Len[who]){
            while(j!=-1 && mo[j]!=StrGroup[who][i]) j = Next[j];
            i++, j++;
        }
        if(j == moL) return true;
        return false;
    }
    bool RunMatch()
    {
        GetNext();
        for(int i=1; i<=num; i++){
            if(i!=index){
                if(!RunKmp(i)) return false;
            }
        }return true;
    }
    
    inline void Find_Better_Ans(int st, int len)
    {
        for(int i=st+1; i<=MinL-len; i++){
            for(int j=i,k=0; k<len; j++,k++){
                //printf("ok %s
    ", ans);
                if(ans[k] > StrGroup[index][j]){
                    mo = substring(i, i+len-1);
                    moL = strlen(mo);
                    if(RunMatch()){
                        free(ans);
                        ans = mo;
                        break;
                    }else{ free(mo); break; }
                }else if(ans[k] < StrGroup[index][j]) break;
            }
        }
    }
    
    bool Match(int len)
    {
        for(int i=0; i<=MinL-len; i++){
            moL = len;
            mo = substring(i, i+len-1);
            if(RunMatch()){
                ans = mo;
                Find_Better_Ans(i, len);
                return true;
            }else free(mo);
        }return false;
    }
    inline void PrintAns()
    {
        for(int len=MinL; len>0; len--)
            if(Match(len)){ puts(ans); free(ans); return; }
        puts("IDENTITY LOST");
    }
    int main(void)
    {
        while(~scanf("%d", &num) && num){
            MinL = 0x3f3f3f3f;
            for(int i=1; i<=num; i++){
                scanf("%s", StrGroup[i]);
                Len[i] = strlen(StrGroup[i]);
                if(MinL > Len[i]){
                    MinL = Len[i];
                    index = i;
                }
            }PrintAns();
        }
        return 0;
    }
    View Code
  • 相关阅读:
    poj 1321 棋盘问题 (DFS深度优先搜索)
    HDOJ1312 Red and black(DFS深度优先搜索)
    《数据结构》例1.3
    hdoj1905 Pseudoprime numbers (基础数论)
    百练4003 十六进制转十进制(水题)
    第二天——2.23
    第一天——2.22
    返校——2.21
    被盗号了——2.19
    继续咸鱼——2.18
  • 原文地址:https://www.cnblogs.com/qwertiLH/p/7582379.html
Copyright © 2011-2022 走看看