字符串截取模板 && 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]=‘\0‘;
    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]=‘\0‘;
    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;
}

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]=‘\0‘;
    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\n", 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;
}

时间: 2024-10-22 10:04:48

字符串截取模板 && POJ 3450、3080 ( 暴力枚举子串 && KMP匹配 )的相关文章

hdu_2328_Corporate Identity(暴力枚举子串+KMP)

题目链接:hdu_2328_Corporate Identity 题意: 给你n个串,让你找这n个串的最大公共子串 题解: 串比较小,暴力枚举第一个的子串,然后KMP判断是否可行 1 #include<cstdio> 2 #include<cstring> 3 #define F(i,a,b) for(int i=a;i<=b;i++) 4 5 const int N=210; 6 int nxt[N],n,lens[4001],ans,l,r,cnt; 7 char dt[

POJ 题目3080 Blue Jeans(KMP+暴力)

Blue Jeans Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 14303   Accepted: 6367 Description The Genographic Project is a research partnership between IBM and The National Geographic Society that is analyzing DNA from hundreds of thousa

Thinkphp 模板中直接对数据处理 模板中使用函数 中文字符串截取

1.Thinkphp 模板中直接对数据处理:{$data.name|substr=0,3} 2.中文字符串截取函数:mb_substr=0,14,'utf-8' 3.中文字符串统计:iconv_strlen(字符串,"UTF-8") <div style="margin-bottom: 8px;"> <a href="#" target="_blank" class="my_a" >

POJ 2739 Sum of Consecutive Prime Numbers( *【素数存表】+暴力枚举 )

Sum of Consecutive Prime Numbers Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 19895   Accepted: 10906 Description Some positive integers can be represented by a sum of one or more consecutive prime numbers. How many such representatio

POJ 3450 Corporate Identity KMP题解

本题要求求一组字符串的最长公共子串,其实是灵活运用KMP快速求最长前缀. 注意肯爹的题意:要求按照字典顺序输出. 还有要提醒的就是:有人也是用KMP来解这道题,但是很多人都把KMP当成暴力法来用了,没有真正处理好细节,发挥KMP的作用.而通常这些人都大喊什么暴力法可以解决本题,没错,的确暴力法是可以解决本题的,本题的数据不大,但是请不要把KMP挂上去,然后写成暴力法了,那样会误导多少后来人啊. 建议可以主要参考我的getLongestPre这个函数,看看是如何计算最长前缀的. 怎么判断你是否把本

ZOJ3818-Pretty Poem(暴力枚举)

题目链接 题意:求所给字符串是否符合ABABA或者ABABCAB的形式,如果可以的话输出Yes,不可以的话为No. 思路:暴力枚举A和B的长度,再用从长度减去3倍的AB长度,即为C的长度,看组合而成的字符串是否与给定的相等.在这里string中的substr函数是个好东西. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <string> #include <a

暴力枚举总述

暴力枚举总述 暴力枚举就是就是把所有可能的答案一一列举出来再加以判断.虽然方法有些笨,但问题规模不大或者没有好的解法时,这也是一个能用的方法. 问题一:输入1~9范围内的整数n,字典序输出1~n这n个数的全排列. 分析:每个数字都是n位数,可看做由前缀A和后缀B组成.初始时前缀A为空.函数伪代码见下: void f(A,B){ //要求的全排列为:已确定的字符串A加上B集合中数字的全排列 if(B为空)  {输出全排列,return;} for(i=1;i<=n;i++){ 若数字i在B中,f(

C# 之 字符串截取--Split

        上一篇博客<C# 之 字符串截取--Substring> 介绍了Substring函数,同时实现将"所属机构名称/教师姓名/课程类型/课程名称"中的所属机构名称,教师姓名,课程类型,课程名称分别截取出来.今天再给大家介绍一种字符串截取的函数Split. String.Split方法:返回的字符串数组包含此实例中的子字符串(由指定 Unicode 字符数组(separator)的元素分隔). String.Split方法的重载方法有六种类型,但是我觉得都大同小

2014网选ZOJPretty Poem(暴力枚举)

/* 将给定的一个字符串分解成ABABA 或者 ABABCAB的形式! 思路:暴力枚举A, B, C串! */ 1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<string> 5 6 using namespace std; 7 string str; 8 char ch[55]; 9 int main(){ 10 int t; 11 scanf("%d&