小明找前缀100000(假)

题目背景

小明最近上课天天睡觉,于是啥都不会。

一天,老师终于点兵点将点到他回答问题,你能帮他渡过难关吗?

现在老师给了小明 n 个由 0、1 构成的字符串,然后有 m 次询问,

每次询问给出一个由 0、1 构成的字符串,

小明需要在最开始的 n 个字符串中找出和当前字符串匹配的前缀最长的串。

如果有多个前缀最长的串,请找出字典序最小的那个。

如果小明找不出来,小明就无了,你能帮助小明吗?

输入格式:

输入第一行是一个整数 t ,表示有 t 组测试实例。

对于每组输入:

输入第一行包含一个整数 n ,代表接下来有 n 行。

接下来 n 行,每行1个字符串,字符串只由0、1构成。

接下来这一行有一个整数 m ,表示询问次数。

接下来 m 行,每行1个字符串,字符串只由0、1构成。

对于每一次询问,你需要求出匹配的前缀最长的字符串,如果有多个答案,请输出字典序最小的那个。

输出格式:

对于每组输入:

输出共 m 行,每行一个字符串对应询问的答案。

输入样例:

2
5
0100
0101
011
10110
10111
1
10011011
4
01
1001
1011100
00110
2
100011
01100

输出样例:

10110
1001
01

 先上超时代码(14分)

#include
using namespace std;
#define endl '\n'
vectorv;
int N, t;
string str;
void sove()
{
    v.clear();
    cin >> N;
    while (N--)
    {
        cin >> str;
        v.emplace_back(str);
    }
    sort(v.begin(), v.end());
    cin >> N;
    while (N--)
    {
        cin >> str;
        int res = 0;
        string ch ;
        ch += str[0];
        auto it = lower_bound(v.begin(), v.end(), ch);
        string ans = v[(int)(it - v.begin())];
        int pos = (int)(it - v.begin());
        for (int i = pos; i < v.size(); i++)
        {
            int len = 0;
            for(int j = 0;j < v[i].size();j++)
                if(str[j] == v[i][j])len++;
            else break;
            if(len >= res) 
            {
                if(len > res)res = len,ans = v[i];
                else
                 ans = min(ans,v[i]);
            }
            else break;
        }
        cout << ans << endl;
    }
}

int main()
{
    cout.tie(0);
    cin.tie(0)->sync_with_stdio(false);
    cin >> t;
    while (t--)
        sove();
    return 0;
}

如何解决?>>01树(本质就是字典树,算是字典树的特殊情况,即树中元素均为0或1)

受不了这个模拟(有点麻烦讲真的)

#include
using namespace std;
#define endl '\n'
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
const int maxn = 500 + 10;
int n, t, m;
bool is = true;
string str;
struct Tree
{
    char ch;
    bool flag;
    Tree* L, * R;
    Tree(char c) :ch(c), L(NULL), R(NULL), flag(false) {};
};

Tree* Built_01Tree(Tree* root, string str, int w)
{
    if(str.size() == 1)
    {
        if(str[w] == '1'&& !root -> L)
        {
            root -> L = new Tree('1');
            root -> L -> flag = true;
        }
        else if(str[w] == '0' && !root -> R)
        {
            root -> R = new Tree('0');
            root -> R -> flag = true;
        }
        else
        {
            str[w] == '1' ? root -> L -> flag = true : root -> R -> flag = true;
        }
            return root;
    }
    if (w == str.size())return NULL;
    if (!root)
        root = new Tree(str[w]);
    if (w == str.size() - 1) root -> flag = true;
    else if (root->ch == str[w] && w + 1 <= str.size())
        str[w + 1] == '1' ? root->L = Built_01Tree(root->L, str, w + 1) : root->R = Built_01Tree(root->R, str, w + 1);
    else if (root->ch != str[w] && w + 1 <= str.size())
        str[w] == '1' ? root->L = Built_01Tree(root->L, str, w) : root->R = Built_01Tree(root->R, str, w);
    return root;
}

string Find(Tree* root, string str, int w)
{
    string ans;
    if (!root)return ans;
    ans += root -> ch;
    if(is)
    {
        if(w >= str.size() && root -> flag)return ans;
        if(root -> flag && !is) return ans;
        if(root -> flag && w == str.size())return ans;
        if(root -> R && root -> R -> ch == str[w])ans += Find(root -> R,str,w + 1);
        else if(root -> L && root -> L -> ch == str[w])ans += Find(root -> L,str,w + 1);
        else
        {
            is = false;
            if(root -> flag)return ans;
            root -> R ? ans += Find(root -> R,str,w + 1) : ans += Find(root -> L,str,w + 1);
        }
    }
    else
    {
        if(root -> flag)return ans;
        //if(root -> flag && w == str.size())return ans;
        root -> R ? ans += Find(root -> R,str,w + 1) : ans += Find(root -> L ,str,w + 1);
    }
    return ans;
};

void pre_cout(Tree* root)
{
    if (!root)return;
    cout << root->ch;// << " ";
    pre_cout(root->L);
    pre_cout(root->R);
}

void solve()
{
    cin >> n;
    Tree* root = new Tree('H');
    while (n--)
    {
        cin >> str;
     //   cout << str << endl;
        Built_01Tree(root, str, 0);
    }
    // pre_cout(root);
    // cout << endl;
    cin >> n;
    while (n--)
    {
        cin >> str;
        is = true;
        string ans = Find(root, str, 0);
        ans.erase(0, 1);
        cout << ans << endl;
    }
}

int main()
{
    IOS
        cin >> t;
    while (t--)
        solve();
    return 0;
}

// //H101110011010
// //H101110001010110





小明找前缀100000(假)_第1张图片

其中:对于答案的求法:情况如下:

1:  如果有当前前缀可以匹配则继续向下搜索

2 : 如果当前前缀无法匹配且改结点是一个01串的终点,结束搜索返回答案

3:如果当前前缀无法匹配但是改结点不是01串终点,根据输出字典序最小的,先访问0结点位置是否存在,存在向0方向搜索,反之向1方向搜索

将测试代码剔除后,有效代码如下:

#include
using namespace std;
#define endl '\n'
int n, t, m;
bool is = true;
string str;
struct Tree
{
    char ch;
    bool flag;
    Tree* L, * R;
    Tree(char c) :ch(c), L(NULL), R(NULL), flag(false) {};
};

Tree* Built_01Tree(Tree* root, string str, int w)
{
    if(str.size() == 1)
    {
        if(str[w] == '1'&& !root -> L)
        {
            root -> L = new Tree('1');
            root -> L -> flag = true;
        }
        else if(str[w] == '0' && !root -> R)
        {
            root -> R = new Tree('0');
            root -> R -> flag = true;
        }
        else
            str[w] == '1' ? root -> L -> flag = true : root -> R -> flag = true;
            return root;
    }
    if (!root)
        root = new Tree(str[w]);
    if (w == str.size() - 1) root -> flag = true;
    else if (root->ch == str[w] && w + 1 <= str.size())
        str[w + 1] == '1' ? root->L = Built_01Tree(root->L, str, w + 1) : root->R = Built_01Tree(root->R, str, w + 1);
    else if (root->ch != str[w] && w + 1 <= str.size())
        str[w] == '1' ? root->L = Built_01Tree(root->L, str, w) : root->R = Built_01Tree(root->R, str, w);
    return root;
}

string Find(Tree* root, string str, int w)
{
    string ans;
    if (!root)return ans;
    ans += root -> ch;
    if(is)
    {
        if(w >= str.size() && root -> flag)return ans;
        if(root -> R && root -> R -> ch == str[w])ans += Find(root -> R,str,w + 1);
        else if(root -> L && root -> L -> ch == str[w])ans += Find(root -> L,str,w + 1);
        else
        {
            is = false;
            if(root -> flag)return ans;
            root -> R ? ans += Find(root -> R,str,w + 1) : ans += Find(root -> L,str,w + 1);
        }
    }
    else
    {
        if(root -> flag)return ans;
        root -> R ? ans += Find(root -> R,str,w + 1) : ans += Find(root -> L ,str,w + 1);
    }
    return ans;
};

void solve()
{
    cin >> n;
    Tree* root = new Tree('H');
    while (n--)
    {
        cin >> str;
        Built_01Tree(root, str, 0);
    }
    cin >> n;
    while (n--)
    {
        cin >> str;
        is = true;
        string ans = Find(root, str, 0);
        ans.erase(0, 1);
        cout << ans << endl;
    }
}

int main()
{
    cin.tie(0) -> sync_with_stdio(false);
        cin >> t;
    while (t--) solve();
    return 0;
}

你可能感兴趣的:(PTA题目集,算法,c++,数学建模)