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 3624 Charm Bracelet (01背包)
    51Nod 1085 背包问题 (01背包)
    POJ 1789 Truck History (Kruskal 最小生成树)
    HDU 1996 汉诺塔VI
    HDU 2511 汉诺塔X
    HDU 2175 汉诺塔IX (递推)
    HDU 2077 汉诺塔IV (递推)
    HDU 2064 汉诺塔III (递推)
  • 原文地址:https://www.cnblogs.com/qwertiLH/p/7582379.html
Copyright © 2011-2022 走看看