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

来源:互联网 发布:windows linux文件传输 编辑:程序博客网 时间:2024/04/30 14:55
Substrings
Time Limit: 1000MS Memory Limit: 10000KTotal 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

23ABCDBCDFFBRCD2roseorchid

Sample Output

22 题目大意:给出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::nposusing 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;}