现在有一些由英文字符组成的大小写敏感的字符串,你的任务是找到一个最长的字符串x,使得对于已经给出的字符串中的任意一个y,x或者是y的子串,或者x中的字符反序之后得到的新字符串是y的子串。
题目来源:百练2744
输入描述
输入:输入的第一行是一个整数t (1 <= t <= 10),t表示测试数据的数目。对于每一组测试数据,第一行是一个整数n (1 <= n <= 100),表示已经给出n个字符串。接下来n行,每行给出一个长度在1和100之间的字符串。
这里是引用
2
3
ABCD
BCDFF
BRCD
2
rose
orchid
输出:
2
2
这里是引用
输出描述
对于每一组测试数据,输出一行,给出题目中要求的字符串x的长度。
思路
对每组测试数据,设置一个int型变量minlen记录最小子串的长度,复制最小子串为minstr。从minlen开始依次递减,测试minstr的不同长度的子串能否满足题目要求,若满足则输出子串长度,若找不到满足要求的子串则输出0。
具体实现
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int main(){
int t;
scanf("%d", &t);
while(t--){
int n;
scanf("%d", &n);
char str[110][110];
char minstr[110];
int minlen = 100;
char subStr[110];
char revsubStr[110];
bool foundMaxSubStr = true;
for(int i = 0; i < n; i++){
scanf("%s", str[i]);
if(strlen(str[i]) < minlen){
minlen = strlen(str[i]);
strcpy(minstr, str[i]);
}
}
for(int i = minlen; i > 0; i--){
int j = minlen - i ;
while(j >= 0){
strncpy(subStr, minstr + j, i);
strncpy(revsubStr, minstr + j, i);
subStr[i] = revsubStr[i] = '\0';
reverse(revsubStr, revsubStr + i);
foundMaxSubStr = true;
for(int k = 0; k < n; k++){
if(strstr(str[k], subStr) == NULL && strstr(str[k], revsubStr) == NULL){
foundMaxSubStr = false;
break;
}
}
if(foundMaxSubStr){
printf("%d\n", i);
break;
}
j-- ;
}
if(foundMaxSubStr)break;
}
if(foundMaxSubStr == false) printf("0");
}
return 0;
}
时间复杂度
小结
strncpy取子串时,需要在末尾添加’\0’
百练OJ的库函数没有strrev函数,需要用reverse,reverse需要传入开始和结尾的地址参数,而非元素参数
(对数组a来说,reverse(a, a + n),而不是reverse(a[0], a[n - 1])。对字符串string来说,reverse(string.begin(), string.end()) )
不要忘记找不到所需字符串时,foundMaxSubStr为false,此时还应输出0