题目描述
思路介绍
①字符串匹配问题,直接用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 ;
}
}
}