ComputerGame---Sunday算法的应用

题目描述

这里写图片描述

这里写图片描述

思路介绍

①字符串匹配问题,直接用BF暴力搜索也可以做不过这个题有时间限制所以不可以用
②第一反应是想到课上高老师讲的KMP算法,不过翻了翻书还是觉得算了,那个while循环那里实在是不好理解,也记不住大致的代码,遇到新题还是懵逼。
③在网上搜了一下,有一个叫sunday算法的,可以借鉴一下,下面就贴一下自己解决这个题的代码。
#include <iostream>
#include <string>
using namespace std ;
int _next[256] = {0} ;
void set_next(int first_number,int first_arr[])
{
    for(int i = 0 ; i < 256 ; i ++ )
    {
        _next[i] = -1 ;
    }
    for(int i = 0 ; i < first_number ; i ++ )
    {
        _next[first_arr[i]] = i  ;
    }
}
int main()
{
    int first_number = 0 ;
    int second_number = 0 ;
    cin >> first_number ;
    int *first_arr = new int[first_number]() ;
    for(int i = 0 ; i < first_number ; i ++ )
    {
        cin >> first_arr[i] ;
    }
    cin >> second_number ;
    int *second_arr = new int[second_number]() ;
    for(int i = 0 ; i < second_number ; i ++ )
    {
        cin >> second_arr[i] ;
    }
    set_next(first_number,first_arr);
    bool judge = false ;
    for(int i = 0 ;  i <= second_number - first_number ;)
    {
        int j = i ;//记录第二个数组遍历的位置 
        int k = 0 ;//记录第一个数组遍历的位置
        while( k < first_number && j < second_number )
        {
            if(first_arr[k] == second_arr[j])
            {
                j ++ ;
                k ++ ;
            }
            else
            {
                break ;
            }
        }
        if( k == first_number )
        {
            cout << i << endl ;
            judge = true ;
            break ;
        }
        else
        {
            if( i + first_number < second_number )
               i = first_number - (_next [ first_arr [ i + first_number]]);
            else
            {
                break ;
            }
        }
    }
    if(judge == false)
    {
        cout << "no solution" << endl ;
    }
}

运算的结果没有问题可是还是超时
这里写图片描述
这就让人很烦了,然后我就想哪里可以继续优化。


想了一下应该是这段代码while循环里面的操作太繁杂了

for(int i = 0 ;  i <= second_number - first_number ;)
    {
        int j = i ;//记录第二个数组遍历的位置 
        int k = 0 ;//记录第一个数组遍历的位置
        while( k < first_number && j < second_number )
        {
            if(first_arr[k] == second_arr[j])
            {
                j ++ ;
                k ++ ;
            }
            else
            {
                break ;
            }
        }
        if( k == first_number )
        {
            cout << i << endl ;
            judge = true ;
            break ;
        }
        else
        {
            if( i + first_number < second_number )
               i = first_number - (_next [ first_arr [ i + first_number]]);
            else
            {
                break ;
            }
        }
    }

可以简化while里面的操作,写成这样

for(int i = 0 ;  i <= second_number - first_number ;)
    {
        int j = 0 ;//记录第一个数组遍历的位置 
        while( j < first_number )
        {
            if( first_arr[j] == second_arr[i] )
            {
                i ++ ;
                j ++ ;
            }
            else
            {
                int n = i - j + first_number ;
                i = n ; 
                //这里直接跳到相应的匹配的块
                while(_next[second_arr[i]] == -1 && i <= second_number - first_number )
                {
                    i ++ ;
                }
                i = n - _next[second_arr[n]] ;
                break ;
            }
        }
        if( j == first_number )
        {
            cout << i - first_number << endl ;
            judge = true ;
            break ;
        }
    }

然后还是MA,这就很僵了,后来看了看discuss原来是题目没有给测试样例的数目,得自己用while判断结束(真的是无与伦比的坑人!!!!)


最后附上(完整代码)

#include <iostream>
#include <string>
using namespace std ;
int _next[256] = {0} ;
void set_next(int first_number,int first_arr[])
{
    for(int i = 0 ; i < 256 ; i ++ )
    {
        _next[i] = -1 ;
    }
    for(int i = 0 ; i < first_number ; i ++ )
    {
        _next[first_arr[i]] = i  ;
    }
}
int main()
{
    int first_number = 0 ;
    int second_number = 0 ;

    while(cin >> first_number)
    {
        int *first_arr = new int[first_number]() ;
        for(int i = 0 ; i < first_number ; i ++ )
        {
            cin >> first_arr[i] ;
        }
        cin >> second_number ;
        int *second_arr = new int[second_number]() ;
        for(int i = 0 ; i < second_number ; i ++ )
        {
            cin >> second_arr[i] ;
        }
        set_next(first_number,first_arr);
        bool judge = false ;
        int i = 0 ;
        while( i <= second_number - first_number )
        {
            int j = 0 ;//记录第一个数组遍历的位置 
            while( j < first_number )
            {
                if( first_arr[j] == second_arr[i] )
                {
                    i ++ ;
                    j ++ ;
                }
                else
                {
                    int n = i - j + first_number ;
                    i = n - _next[second_arr[n]] ;
                    break ;
                }
            }
            if( j == first_number )
            {
                cout << i - first_number << endl ;
                judge = true ;
                break ;
            }
        }
        delete []first_arr;
        delete []second_arr ;
        if(judge == false)
        {
            cout << "no solution" << endl ;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值