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