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; }