ACM-ICPC 2017 Asia Qingdao J. Suffix (二分 HASH LCP或者暴力)aa

Consider n given non-empty strings denoted by s1 , s2 , · · · , sn . Now for each of them, you need to select a corresponding suffix, denoted by suf1, suf2, · · · , sufn. For each string si, the suffix sufi is a non-empty substring whose right endpoint is the endpoint of the entire string. For instance, all suffixes of the string “jiangsu” are “u”, “su”, “gsu”, “ngsu”, “angsu”, “iangsu” and itself.

All selected suffixes could assemble into a long string T = suf_1suf1​ + suf_2suf2​ + · · · + suf_nsufn​ . Here plus signs indicate additions of strings placing the latter at the tail of the former. Your selections of suffixes would determine the lexicographical order of T . Now, your mission is to find the one with minimum lexicographical order.

Here is a hint about lexicographical order. To compare strings of different lengths, the shorter string is usually padded at the end with enough “blanks” which is a special symbol that is treated as smaller than every letters.

Input

The first line of input contains an integer T which is the total number of test cases. For each case, the first line contains an positive integer n. Each of the following n lines contains a string entirely in lowercase, corresponding to s_1s1​ , s_2s2​ , · · · , s_nsn​ . The summation of lengths of all strings in input is smaller or equal to 500000.

Output

For each test case, output the string T with minimum lexicographical order.

样例输入复制

3
3
bbb
aaa
ccc
3
aba
aab
bab
2
abababbaabbababba
abbabbabbbababbab

样例输出复制

baaac
aaabab
aab

题目来源

ACM-ICPC 2017 Asia Qingdao

 

 

题意:

给你n个字符串,你需要依次从每个字符串选一个后缀拼接起来,问字典序最小的串是什么?

分析:

这题需要逆向思维,每一次选择字典序最小的即可。

举一个例子:

3

aba

aab

bab

  1. 对于bab,我们有三种选择bab,ab,b,我们选择字典序最小的ab,然后我们把ab放到aabab上去。
  2. 对于aabab,我们有三种选择aabab,abab,bab。我们选择字典序最小的aabab。

下面同理即可。
 

这题暴力就可以过了,要想加快速度的话,可以求比较的时候利用二分+HASH或后缀数组求两个字符串的LCP,然后比较lcp后的第一个字符。

HASH:95ms

#include
using namespace std;
typedef long long LL;
typedef  unsigned long long ULL;
const ULL base=131;
const int  N=500005;
char ans[N];
string str[200005];
ULL Hash1[N],pw[N];
int anslen,nowlen,sumlen;
int len[N];
void init()
{
    pw[0]=1;
    for(int i=1; i<=N; i++)
    {
        pw[i]=pw[i-1]*base;
    }
}
ULL getHash(int l,int r)
{
	 return Hash1[r]-Hash1[l-1]*pw[r-l+1];
}
int main()
{
    int T;
    scanf("%d",&T);
    init();
    while(T--)
    {
    	str[0]="";
        int n;
        scanf("%d",&n);
        sumlen=0;
        for(int i=1; i<=n; i++)
        {
            cin>>str[i];
            len[i]=str[i].size();
        }

      

        for(int i=n; i>=1; i--)
        {
            nowlen=str[i].size();
            for(int j=0; j>1;
                  if(getHash(pos,pos+mid-1)==getHash(j,j+mid-1))
                  {
                  	l=mid;
                  }
                  else
                  	r=mid-1;
                } 
                /*cout<str[i][j-1+l])
                {
                    pos=j;
                }
            }
            str[i-1]+=str[i].substr(pos-1,nowlen-pos+1);
            //cout<<"$"<

 

暴力:486ms

#include
using namespace std;
typedef long long LL;
typedef  unsigned long long ULL;
const ULL base=131;
const int  N=500005;
char ans[N];
string str[200005];
ULL Hash1[N],pw[N];
int anslen,nowlen,sumlen;
int len[N];
void init()
{
    pw[0]=1;
    for(int i=1; i<=N; i++)
    {
        pw[i]=pw[i-1]*base;
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    init();
    while(T--)
    {
    	str[0]="";
        int n;
        scanf("%d",&n);
        sumlen=0;
        for(int i=1; i<=n; i++)
        {
            cin>>str[i];
            len[i]=str[i].size();
        }

        anslen=1;
        nowlen=1;

        for(int i=n; i>=1; i--)
        {

            /*for(int j=0; j>1;
                  if(getHash(pos,pos+mid-1)==gethash(j,j+mid-1))
                  {
                  	l=mid;
                  }
                  else
                  	r=mid-1;
                }         */
               
                if(str[i].substr(pos-1,nowlen-pos+1)>str[i].substr(j-1,nowlen-j+1) )
                {
                    pos=j;
                }
            }
            str[i-1]+=str[i].substr(pos-1,nowlen-pos+1);
            //cout<<"$"<

 

你可能感兴趣的:(好题)