吐槽:(直接忽视)首先,写下第一次敲这个代码的感悟:好吧,找错找了3天的一题,然后错误找到,数组开小了,然后找呀找呀,找呀找,然后怀疑自己的思路,虽然稍微麻烦点,可能超时神马的,但是不应该WA呀,于是自己深刻反省反省,自己的思路到底有何问题,最后发现没问题,错在哪?错在蛋痛的数组开小了上。哥不就是数组开小了,你应该给我报个RE呀,你报个RE给我,我再错,我也就不说啥了,但是你妹的一直给我报WA是何居心,然后我就一直没往数组开小了这方面想。好吧,还是自己不够细心,一开始数组开小了。。。
正题:先写一下自己最初不是很成熟的算法,速度很慢,但是很容易想到。看到有人用KMP模板,或者一些挺牛的算法直接水掉,自己那是一个蛋痛,写完这段代码后继续在写稍微升级点的版本。不断优化,然后学习一些KMP,毕竟现在还是新手阶段,慢慢来吧、
题意:给了n个测试的字符串,然后要求求出这n个字符串最长的共同的子串的长度,(注意:正序和逆序如果有这个子串都成立,就是正序逆序的都要检查),输出最长的长度就好。
分析:思路就是,先将正序和逆序的数组都求出来,求逆序的时候用了一个sttrev,查了下函数手册,是用在字符数组中的,在cstring中,然后我是用string写的,所以就自己重载了一遍,用了个反向迭代器,就是rbegin和rend。存完了正序逆序的数组后,在求完子串之前都用正序的字符串就行了。然后,先筛选出最短的字符串,
再用一个数组存储下所有的子串,用了substr函数,(这样的存储比较耗时,也就导致了最后的运行时间比较长,需要数组范围比较大,其实完全可以从最长的子串开始筛选,会省很多时间,如果成立,就能直接结束循环,第二次写的时候就按这种思路改),然后用了一个find函数去筛选(不过看别人大多数都是用的strstr,暂时还不知道怎么用,去研究研究去),最后筛选的所有的子串的结果的长度重新存一个length[10000]数组中,用下sort函数去排序,输出最大的就行了。
第一次写的整体的思路很简单,虽然实现稍微复杂点,但是不用考虑太多东西。第二次写的时候要改进一下
贴一下AC代码吧,速度比较慢:(764k,110ms)
#include<iostream>
#include<string>
#include<algorithm>
using
namespace
std;
string
sttrev(
string
a)
//将字符串逆序
{
string
str(
a
.
rbegin
(),
a
.
rend());
return
str;
}
int
main()
{
string
a
[
105
][
2
];
int
length
[
105
];
int
original_length
[
105
];
int
temp_length
[
105
];
string
sub_string
[
10000
];
int
i
,
j ;
int
num;
//用于记录是第几个数据
int
t
, n;
cin
>>
t;
while (
t
--)
{
int
temp
,
number
[
10000
]
=
{
0
};
int
temp_number
[
2
]
=
{
0
};
cin
>>n;
for(
i
=
0;
i
< n;
i
++)
//直接存储正序和逆序的字符串
{
cin
>>
a
[
i
][
0
];
a
[
i
][
1
]
=
sttrev(
a
[
i
][
0
]);
length
[
i
]
=
a
[
i
][
0
].
length();
original_length
[
i
]
=
length
[
i
];
}
sort(
length
,
length
+n);
for(
i
=
0;
i
< n ;
i
++)
{
if(
original_length
[
i
]
==
length
[
0
])
//选择出最短的一段字符串,节省后面的筛选时间
{
num
=
i;
break;
}
}
temp
=
0;
for(
i
=
0;
i
<
length
[
0
];
i
++)
{
for(
j
=
length
[
0
]
-
i;
j
>=
1 ;
j
--)
{
sub_string
[
temp
]
=
a
[
num
][
0
].
substr(
i
,
j);
temp
++;
}
}
for(
i
=
0;
i
<
temp ;
i
++)
{
for(
j
=
0;
j
< n;
j
++)
{
temp_number
[
0
]
=
a
[
j
][
0
].
find(
sub_string
[
i
]);
//cout<<"text0:"<<temp_number[0]<<endl;
temp_number
[
1
]
=
a
[
j
][
1
].
find(
sub_string
[
i
]);
//cout<<"text1:"<<temp_number[1]<<endl;
if((
temp_number
[
0
]
>=
0) ||(
temp_number
[
1
]
>=
0))
number
[
i
]
++;
//注意。如果是子串是第一个字母开始的话,也要加1,因为substr返回的是字符串第一次出现的位置
}
}
j
=
0;
for(
i
=
0;
i
<
temp;
i
++)
if(
number
[
i
]
== n )
{
temp_length
[
j
]
=
sub_string
[
i
].
length();
j
++;
}
if(
j
>
0)
{
sort(
temp_length
,
temp_length
+
j);
cout
<<
temp_length
[
j
-
1
]
<<
endl;
}
else
cout
<<
0
<<
endl;
}
}