poj1226 Substrings (应该用kmp,但是数据弱,暴力枚举就行了)

Substrings
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 10938 Accepted: 3793

Description

You are given a number of case-sensitive strings of alphabetic characters, find the largest string X, such that either X, or its inverse can be found as a substring of any of the given strings.

Input

The first line of the input contains a single integer t (1 <= t <= 10), the number of test cases, followed by the input data for each test case. The first line of each test case contains a single integer n (1 <= n <= 100), the number of given strings, followed by n lines, each representing one string of minimum length 1 and maximum length 100. There is no extra white space before and after a string.

Output

There should be one line per test case containing the length of the largest string found.

Sample Input

2
3
ABCD
BCDFF
BRCD
2
rose
orchid

Sample Output

2
2 
题目大意:给出n个字符串,求出n个字符串的最大字串的长度。注意:子串和子序列是有区别的,前者必须连续,后者可以不连续。

解体思路:本题从理论上来讲,如果数据大一点的话应该用kmp,但是由于本题的数据很弱,所以暴力枚举长度就行了,具体方法如下。

第一:找出n个字符串中最小的那个,strTmp[],其长度为min_len(因为最大子串的长度也只能是strTmp[],不可能有比它还大的)
第二:按照长度递减的方式,依次枚举strTmp[]长度为len的子串(即,{strTmp[i]...strTmp[i+len]},其中0<=i<=min_len-len,看该子串是否是所有的字符串的子串
      如果是,就立刻跳出所有枚举的循环,并输出(因为是按从大到小的方式枚举)
      否则,则继续第二步;

代码:我写了两个,一个是C风格的字符串处理方式,另一个是C++风格,C++的stl确实慢了一点,但是并有想象中那么不可接受,他确实方便,可读性高。

纯C风格字符串处理(学会strstr()查找匹配函数)
/*
    @author : liuwen
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <stack>
#include <map>
#include <vector>
#include <cmath>
using namespace std;
const int maxn=105;
int main()
{
    //freopen("in.txt","r",stdin);
    int T,n;
    scanf("%d",&T);
    while(T--){
        char str[maxn][maxn],str1[maxn],pos[maxn],inv[maxn];
        int min_len,len,index;
        scanf("%d",&n);
        index=0,min_len=105;
        for(int i=0;i<n;i++){
            scanf("%s",str[i]);
            if(strlen(str[i])<min_len){
                min_len=strlen(str[i]);
                index=i;
            }
        }
        strcpy(str1,str[index]);
        for(len=min_len;len>0;len--){ //枚举子字符串的长度len,从长到短
            bool flag=false;
            for(int i=0;i<=min_len-len;i++){ //枚举长度为len的字串
                flag=true;
                strncpy(pos,str1+i,len); //其实位置为i,长度为len的正子串
                for(int j=0;j<len;j++){  //反转子符串
                    inv[j]=pos[len-j-1];
                }
                pos[len]=inv[len]='\0';  //转换为字符串

                for(int j=0;j<n;j++){    //看其他字符串是否有该字串或者字串的反串
                    if(strstr(str[j],pos)==NULL&&strstr(str[j],inv)==NULL){ //比较函数strstr()
                        flag=false;
                        break;
                    }
                }
                if(flag)    break;  //如其他字符串都有该字串或者字串的反串,则退出
            }
            if(flag)    break; //同上,原因是我们按从长到短的子字符串的顺序枚举的,因此,最先满足的肯定是最长(大)的
        }
        printf("%d\n",len);
    }
    return 0;
}
C++风格 
/*
    @author : liuwen
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <stack>
#include <map>
#include <vector>
#include <cmath>
#define NOT_FIND string::npos
using namespace std;
const int maxn=105;
string str[maxn];
int main()
{
    //freopen("in.txt","r",stdin);
    int T,n;
    scanf("%d",&T);
    while(T--){
        string strTmp,strPos,strRev,strPosTmp;
        int len,min_len,index;
        scanf("%d",&n);
        min_len=105;
        for(int i=0;i<n;i++){            //输入并找出最小长度字符串
            cin>>str[i];
            if(str[i].length()<min_len){
                min_len=str[i].length();
                index=i;
            }
        }
        strTmp=str[index];            
        for(len=min_len;len>0;len--){    //按长度递减的方式枚举
            bool isFind=false;
            for(int i=0;i<=min_len-len;i++){  //枚举strTmp[]每个长度为len的子串
                isFind=true;
                strPos=strTmp.substr(i,len);  // 正向{strTmp[i]...strTmp[i+len]}
                strRev.resize(strPos.length());  
                reverse_copy(strPos.begin(),strPos.end(),strRev.begin()); //反向
                for(int j=0;j<n;j++){
                    if((int)str[j].find(strPos)==-1&&(int)str[j].find(strRev)==-1){ 
                        isFind=false;//若正向和反向都没找到,find()函数返回-1,则继续枚举strTmp[]中长度为len的子串
                        break;
                    }
                }
                if(isFind)  break; //如果找到,立刻返回
            }
            if(isFind)  break; //如果找到,立刻返回
        }
        printf("%d\n",len);
    }
     /*
     string str1="love";
    string str2;
    str2.resize(str1.length());
    reverse_copy(str1.begin(),str1.end(),str2.begin());
    cout<<str1<<endl;
    cout<<str2<<endl;
     */
    //output is:
    //        love
    //        evol  
     return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值