题目链接:http://acm.swust.edu.cn/problem/0763/
Time limit(ms): 1000 Memory limit(kb): 65535
西南某科技大学的校门外有N排树,每一排树的长度可能不同。每一棵树都用字符作了一个标记。
现在由于学校修建教师公寓,需要在每排树中砍一段连续的树。要求是在每一排树中砍掉的那一段树标记序列都相同。
例如第1排:ABCD,第2排BCDFF,第3排:BRCD,那么我们就可以在每一排树中砍掉CD。请注意下面测试数据的第二组,我们可以砍掉RO,和OR,即只要求标记序列相同,但是在原来那一排树里的方向没有要求。
Description
第一行输入有几组测试数据t (1 <= t <= 10)。
对每一组测试数据,首先输入数字N (1 <= n <= 100)表示有多少排树,每排树的最大长度为100。
接下来的N行,为每一排树的序列。
Input
对于每一组测试数据,输出最多能在一排树砍掉多少棵树。
Output
1 2 3 4 5 6 7 8 9 | 2 3 ABCD BCDFF BRCD 2 rose orchid |
Sample Input
1 2 | 2 2 |
Sample Output
解题思路:直接从大到小暴力枚举所有字符串即可(数据较小,貌似较大用的是后缀数组,并不会Orz~~),不考虑正反,需把字符串反向考虑进来
代码如下:
#include <stdio.h>
#include <string.h>
int main(){
int t, n, i, j, k, L, len, ans;
char str[][], s1[], s2[];
scanf("%d", &t);
while (t--){
int min = , ptr;
scanf("%d", &n);
for (i = ; i < n; i++){
scanf("%s", str[i]);
len = strlen(str[i]);
if (len<min){
min = len;
ptr = i;
}
}
//从大到小枚举所有可能长度
for (i = min; i>; i--){
for (j = ; j <= min - i; j++){
//枚举当前长度下的所有子序列的正反序列
for (k = j, L = ; k <= i + j - ; k++, L++){
s1[L] = str[ptr][k];
s2[L] = str[ptr][j + i - - L];
}
s1[L] = s2[L] = '\0';
for (k = ; k < n; k++){
if (!strstr(str[k], s1) && !strstr(str[k], s2))
break;
}
if (k == n)break;
}
if (k == n)break;
}
printf("%d\n", i);
}
return ;
}