(重要题目)POJ 1226 Substrings(…

吐槽:(直接忽视)首先,写下第一次敲这个代码的感悟:好吧,找错找了3天的一题,然后错误找到,数组开小了,然后找呀找呀,找呀找,然后怀疑自己的思路,虽然稍微麻烦点,可能超时神马的,但是不应该WA呀,于是自己深刻反省反省,自己的思路到底有何问题,最后发现没问题,错在哪?错在蛋痛的数组开小了上。哥不就是数组开小了,你应该给我报个RE呀,你报个RE给我,我再错,我也就不说啥了,但是你妹的一直给我报WA是何居心,然后我就一直没往数组开小了这方面想。好吧,还是自己不够细心,一开始数组开小了。。。

 

 

正题:先写一下自己最初不是很成熟的算法,速度很慢,但是很容易想到。看到有人用KMP模板,或者一些挺牛的算法直接水掉,自己那是一个蛋痛,写完这段代码后继续在写稍微升级点的版本。不断优化,然后学习一些KMP,毕竟现在还是新手阶段,慢慢来吧、(重要题目)POJ <wbr>1226 <wbr>Substrings(子串处理,必须熟练掌握)

 

题意:给了n个测试的字符串,然后要求求出这n个字符串最长的共同的子串的长度,(注意:正序和逆序如果有这个子串都成立,就是正序逆序的都要检查),输出最长的长度就好。

 

分析:思路就是,先将正序和逆序的数组都求出来,求逆序的时候用了一个sttrev,查了下函数手册,是用在字符数组中的,在cstring中,然后我是用string写的,所以就自己重载了一遍,用了个反向迭代器,就是rbegin和rend。存完了正序逆序的数组后,在求完子串之前都用正序的字符串就行了。然后,先筛选出最短的字符串,

再用一个数组存储下所有的子串,用了substr函数,(这样的存储比较耗时,也就导致了最后的运行时间比较长,需要数组范围比较大,其实完全可以从最长的子串开始筛选,会省很多时间,如果成立,就能直接结束循环,第二次写的时候就按这种思路改),然后用了一个find函数去筛选(不过看别人大多数都是用的strstr,暂时还不知道怎么用,去研究研究去),最后筛选的所有的子串的结果的长度重新存一个length[10000]数组中,用下sort函数去排序,输出最大的就行了。

 

第一次写的整体的思路很简单,虽然实现稍微复杂点,但是不用考虑太多东西。第二次写的时候要改进一下

 

贴一下AC代码吧,速度比较慢:(764k,110ms)

 

C++语言:
#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;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值