题目的主要信息:

  • 一组输入整数序列II和一组规则整数序列RRIIRR序列的第一个整数为序列的个数(个数不包含第一个整数)
  • 整数范围为00xFFFFFFFF0至0xFFFFFFFF,序列个数不限
  • RR依次中取出RiR_i,对II进行处理,找到满足条件的IjI_jIjI_j整数对应的数字需要连续包含RiR_i对应的数字,按照RiR_i从小到大的顺序处理,重复元素只处理第一个
  • 对于每个RiR_i如果有满足上述条件的IjI_j,先输出RiR_i,没有就不输出,再输出满足条件的IjI_j的个数,然后输出满足条件的全部索引jj(从0开始),最后再输出全部的IjI_j
  • 最后需要在输出序列的第一个整数位置记录后续整数序列的个数(不包含“个数”本身)
  • 需要处理多组输入的情况

方法一:排序+暴力验证

具体做法:

我们按照题目要求按部就班处理就可以了:

首先根据第一个输入得到II序列的长度nn,然后用vector存储II,然后根据输入得到RR的长度mm,同样利用vector数组存储RR

处理完输入以后先用sort函数对RR序列排序。

然后遍历序列RR,遇到与前一个相同的元素,我们跳过,以此来去重。然后遍历序列II,检查每一个IjI_j中是否包含了连续的RiR_i,如果有我们计数加1,并临时记录符合条件的下标。

如果上面的计数为0,我们不做任何处理。如果不为0,我们将RiR_i加入待输出数组末尾,再将刚刚的计数加在后面,最后遍历刚刚记录下标的数组,依次将下标jj及对应的元素IjI_j加入待输出数组后面。

最后我们统计待输出的数组长度,先在输出数组前输出就行了。

验证的时候,我们首先比较二者大小,然后找到每次ii要除10的多少次方余数才能和rr比较,然后我们就连续对ii除这个值,每次比较余数即可。

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

bool check(int r, int i){//检查数字i包含数字r
    if(r > i) //i比r还小,不可能
        return false;
    int top = 1;
    while(r / top != 0) //记录每次要连续除10的多少次方,余数才能和r比较
        top *= 10;
    if(r == 0)
        top = 10;
    int k = 0;
    while(i * 10 / top != 0){ //连除比较
        if((i % top) == r)
            return true;
        i /= 10;
    }
    return false;
}

int main(){
    int n, m; //记录序列I和序列R的大小
    while(cin >> n){
        vector<int> I(n);
        for(int i = 0; i < n; i++)
            cin >> I[i]; //输入n个整数序列I
        cin >> m; //整数序列R的长度
        vector<int> R(m);
        for(int i = 0; i < m; i++) //输入m个整数序列R
            cin >> R[i];
        sort(R.begin(), R.end()); //排序
        vector<int> res;
        for(int i = 0; i < m; i++){
            if(i != 0 && R[i] == R[i - 1]) //去重
                continue;
            int count = 0;
            vector<int> index; //记录符合条件的下标
            for(int j = 0; j < n; j++){
                if(check(R[i], I[j])){
                    count++;
                    index.push_back(j);
                }
            }
            if(count != 0){ //如果有出现连续的R[i],添加头部的R[i]及后面有多少个数中出现了
                res.push_back(R[i]);
                res.push_back(count);
                for(int j = 0; j < index.size(); j++){
                    res.push_back(index[j]);
                    res.push_back(I[index[j]]);
                }
            }
        }
        cout << res.size(); //先输出个数
        for(int i = 0; i < res.size(); i++) //再逐个输出
            cout << " " << res[i];
        cout << endl;
    }
    return 0;
}

复杂度分析:

  • 时间复杂度:O(nm+mlog2m)O(nm + mlog_2m),其中nn为序列II的长度,mm为序列RR的长度,我们要对于每个RiR_i会对每个IjI_j进行验证,验证的复杂度是常数,因为是数字的十进制位数,而我们也不知道mmnn的具体大小,因此排序复杂度O(mlog2m)O(mlog_2m),要加在后面
  • 空间复杂度:O(n)O(n),辅助数组的最大长度为II序列长度,res数组及保存序列的数组都属于必要空间,不属于额外空间

方法二:哈希表+字符串

具体做法:

对于方法一的排序+去重,我们可以用有序哈希表map实现,输入的RR序列直接进入哈希表,会自动排序去重,后续遍历哈希表就可以了。

而数组作为输出很麻烦,验证是否满足条件也很麻烦,我可以将数字转换成字符串,利用字符串的find函数查找是否出现过,然后所有的待输入的信息我们可以添加到字符串末尾,也可以在其前面添加数量信息及数字RiR_i

alt

#include<iostream>
#include<vector>
#include<algorithm>
#include<map>
using namespace std;

int main(){
    int n, m; //记录序列I和序列R的大小
    while(cin >> n){
        vector<int> I(n);
        for(int i = 0; i < n; i++)
            cin >> I[i]; //输入n个整数序列I
        cin >> m; //整数序列R的长度
        map<int, int> R;
        for(int i = 0; i < m; i++){ //哈希表记录序列R,直接去重加排序
            int t;
            cin >> t;
            R[t] = 1;
        }
        int total = 0;
        string res = ""; //以字符串的形式输出
        for(auto iter = R.begin(); iter != R.end(); iter++){
            int count = 0;
            string temp = ""; //记录这一轮的R[i]有多少匹配的
            for(int i = 0; i < n; i++){
                if(to_string(I[i]).find(to_string(iter->first)) != string::npos){ //找到出现数字
                    count++; //数量加1
                    temp += to_string(i) + ' ' + to_string(I[i]) + ' '; //添加索引和该数字
                }
            }
            if(count != 0){ //如果有出现连续的R[i],添加头部的R[i]及后面有多少个数中出现了
                res += to_string(iter->first) + ' ' + to_string(count) + ' ' + temp;
                total += (2 * count + 2); //补充后面增加了多少数
            }
        }
        res = to_string(total) + ' ' + res; //添加总个数
        cout << res << endl;
    }
    return 0;
}

复杂度分析:

  • 时间复杂度:O(nm+mlog2m)O(nm + mlog_2m),其中nn为序列II的长度,mm为序列RR的长度,我们要对于每个RiR_i会对每个IjI_j进行验证,验证的复杂度是常数,因为是数字的十进制位数,而我们也不知道mmnn的具体大小,因此排序复杂度O(mlog2m)O(mlog_2m),要加在后面
  • 空间复杂度:O(m)O(m),辅助空间为哈希表的长度,res字符串及保存序列的数组都属于必要空间,不属于额外空间