• 1051 接龙游戏


    题目连接

    http://www.wikioi.com/problem/1051/

    题意:给你n个字符串(1<=n<=10^5),查找最长的接龙数,能够接龙的条件是:前一个串是本串的前缀,例如 a --->ab这样就算接龙,但是这里串相同不算接龙,例如

    a---->aaa----aaa 这样的接龙长度算2,然后输出这些串最长能够得到的接龙,输出这个数就ok了;

    一开始看到这题的时候,因为这里的接龙条件是前一个串是后一个串的前缀,就想到了使用字典树来做,因为使用每一个单词了建立字典树,将下一个单词添加进树时,能够得到之前单词,如果之前的单词是这个单词的前缀,这个单词在进行添加进字典树的时候,一定会进过这条路径。

    然后解决这个问题使用的方法是:标记每个单词,当下一个单词经过了这个条路径,得到当前的这个标记,然后本单词在这个基础上加1,在这里要注意重复单词的出现。

    然后记录其中最大的标记数。最后输出这个max

    代码:

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    
    using namespace std;
    
    typedef struct data{
    
        int t;
        data *next[26];
        data()
        {
            t = 0;
            for(int i = 0;i < 26; i++)
                next[i]= NULL;
        }
    }data;
    
    data *head;
    
    int add(char *ch)
    {
        if(head == NULL)
            head = new data();
        data *p = head;
        int t = 0;
        int tmp;
        bool flag = true;
        for(int i = 0; i < strlen(ch); i++)
        {
            flag = true;
            tmp = ch[i] -'a';
            if(p->next[tmp] == NULL)
                p->next[tmp] = new data();
            else
                {
                    t = t > p->next[tmp]->t ? t : p->next[tmp]->t;
                    flag = false;
                }
            p = p->next[tmp];
        }
        if(flag)
            p->t = ++t;
    
        return p->t;
    }
    void print(data *p)
    {
        for(int i = 0; i < 26; i++)
        {
            if(p->next[i] != NULL)
                {
                    printf("%c %d
    ",i+'a',p->next[i]->t);
                    print(p->next[i]);
                }
    
        }
    }
    int main()
    {
        int n;
        scanf("%d",&n);
        char ch[55];
        int max = 0;
        while(n--)
        {
            scanf("%s",ch);
            int t = add(ch);
            max = max > t ? max : t;
        }
       // print(head);
        printf("%d
    ",max);
        return 0;
    }
    

     本代码在wikioi中得分80,内存超了,这个10^5个单词在创建字典树时内存消耗太大。。。。。纠结啊----------------------------

    后来看了一下有人发的解题报告:

    思路是,首先将这些单词进行字典序排序,然后使用一个栈来保存这个接龙,这个字典序排序貌似有两种排序,不知道是不是,但是在这里使用的排序方法是:

    比较单词的每一个位置,字典序小的返回true,大的返回false,当有一个单词比较完后还没有结果,则长度短者返回true 长者false

    自定义排序代码

    typedef struct data{
        string s;
    }data;
    
    bool cmp(data x,data y)
    {
        int len =  x.s.length() < y.s.length() ? x.s.length(): y.s.length();
        for(int i = 0; i < len; i++)
        {
            if(x.s[i] < y.s[i])
                return true;
            else if(x.s[i] > y.s[i])
                return false;
        }
       if(x.s.length() < y.s.length())
            return true;
        else return false;
    }
    

     这样排序后前缀相同的单词都紧挨着了,然后使用栈来保存这个接龙,当单词将要入栈时,栈顶单词是该单词的前缀则进栈,不是则一直从栈中寻找,直到满足条件或是这个栈为空了,然后将这个单词入栈,在处理入栈的同时记录最长的接龙数。最后输出这个max就是答案,但是栈中保存的数据不一定是这个最长接龙的单词,这里已没有要求得到这个接龙。所以这里就不用考虑了。嘻嘻解决-----OK

    代码:

    #include <string>
    #include <algorithm>
    #include <iostream>
    #include <stack>
    using namespace std;
    
    typedef struct data{
        string s;
    }data;
    
    bool cmp(data x,data y)
    {
        int len =  x.s.length() < y.s.length() ? x.s.length(): y.s.length();
        for(int i = 0; i < len; i++)
        {
            if(x.s[i] < y.s[i])
                return true;
            else if(x.s[i] > y.s[i])
                return false;
        }
       if(x.s.length() < y.s.length())
            return true;
        else return false;
    }
    data ch[100007];
    
    int main()
    {
        int n;
       cin>>n;
        for(int i = 0; i < n; i++)
            cin>>ch[i].s;
    
        sort(ch,ch+n,cmp);
        stack<data> mystatck;
        int max = 1;
        mystatck.push(ch[0]);
        data tmp;
        for(int i = 1; i < n; i++)
          {
                tmp = mystatck.top();
                if(ch[i].s.find(tmp.s,0) == 0)
                    {
                        if(tmp.s.length() != ch[i].s.length())
                            mystatck.push(ch[i]);
                    }
                else
                {
                    while( !mystatck.empty()){
                        tmp = mystatck.top();
                        if(ch[i].s.find(tmp.s,0) == 0)
                            break;
                        mystatck.pop();
                    }
                    mystatck.push(ch[i]);
                }
            max = max > mystatck.size() ? max : mystatck.size();
           // cout<<mystatck.size()<<endl;
          }
        cout<<max<<endl;
        return 0;
    }
    
  • 相关阅读:
    Assert.isTrue 用法
    P2967 [USACO09DEC]视频游戏的麻烦Video Game Troubles
    最近目标2333
    LibreOJ β Round #2」贪心只能过样例
    CF1062F Upgrading Cities 拓扑排序
    CF1108F MST Unification
    CF915D Almost Acyclic Graph 拓扑排序
    Swift日历控件Calendar
    README.md的markdown语法
    MAC打开App显示已损坏
  • 原文地址:https://www.cnblogs.com/yyroom/p/3726545.html
Copyright © 2020-2023  润新知