ADV-1184 最小字符串(贪心)


题目描述

给定一些字符串(只包含小写字母),要求将他们串起来构成一个字典序最小的字符串。

输入格式
  第一行T,表示有T组数据。
  接下来T组数据
  每组第一行一个正整数n,表示字符串个数。
  接下来n行,每行一个字符串(长度不超过100)。
  
输出格式
  T行,每行一个字符串。

数据规模和约定
  T<=7000,n<=100;

样例输入

1
3
a
b
c

样例输出

abc

思路

对于整个链接过程,我们需要先的到所有的可用字符串后在进行排序链接,所以简单的排序
无法解决该问题。
首先思考字符串大小比较算法。如果第一位相同,则看第二位,以此类推如果其中一个达到
最后一位只需要对该字符串长度取余即可。于是便可得到比较字符串函数check();
接着思考如果只用两个栈维护结果。那么就是每次来一个新的字符串x,那么我们会与栈顶
元素进行比较q.top()。如果x>q.top();那么直接压入一个x即可,反之则将栈顶元素弹入
预备栈s中。知到找到比x大的字符串或者q中没有字符串,将x压入栈中,并将s中的元素依
次放回,那么便可使得整体字典序最小。(该方法可通过90%)
最后便是最终的优化:
首先上述方法,当数据较为极限时,每次需要将全部元素取出,压入新来的元素,再将全部
元素放回,如此时间复杂度将会非常高。通过思考,我们发现,首字母小的一定在前面。
所以我们可以开26个栈,第0个栈存放开头是a的所有元素,第1个栈存开头是b的所有元素,
以此类推。从而我们每次插入时间只需找到首字母相同的栈进行排序即可。这样插入操作的
时间复杂度便可得到有效的控制。便得到最终结果。(Accept!)

(单调栈) $O(n^2/2)$
时间复杂度分析

优化后如果全部元素首字母都相同,最坏情况下,第2次插入取出1个元素,第3次去2个以此类推
当n为100时,最坏情况下与优化前复杂度相同,为1+2+……+99=4950≈5000,最终复杂度为5000*T
=3.5e7。可以有效accept。

C++ 代码

#include <cstring>
#include <algorithm>
#include <iostream>
#include <stack>

using namespace std;


const int N=110;

stack<string> q[27];
stack<string> s;

bool check(string x,string y)
{
    int n=x.size(),m=y.size();
    int k=max(n,m);
    for(int i=0;i<k;i++)
    {
        if(x[i%n]<y[i%m]) return true;
        if(x[i%n]>y[i%m]) return false;
    }
    return false;
}

void handel(stack<string> &q,stack<string> &s,string x)
{
    if(!q.size()) 
    {
        q.push(x);
        return;
    }
    string str=q.top();
    while(!check(x,str) and q.size())
    {
        q.pop();
        s.push(str);
        if(q.size()) str=q.top();
        else break;
    }
    q.push(x);
    while(s.size())
    {
        string n=s.top();
        s.pop();
        q.push(n);
    }
}

int main()
{
	int T;
	cin>>T;
	while(T--)
	{
	    int n;
	    cin>>n;
	    string str0;
	    for(int i=0;i<n;i++) 
	    {
	        cin>>str0;
    	    int t=str0[0]-'a';
    	    handel(q[t],s,str0);
	    }
	    string res;
	
    	for(int i=0;i<26;i++)
    	{
    	    while(q[i].size())
    	    {
    	        res=res+q[i].top();
    	        q[i].pop();
    	    }
    	}
    	
    	cout<<res<<endl;
	}
	return 0;
	
}


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM