T1 命令方块(block)
(WOJ4816)
1.1 题目描述
实际上这道题与命令方块没有什么关系。给定
n
n
n个字符串
s
i
s_i
si,将它们按给出的顺序排开。你每次可以交换任意两个字符串的位置。
通过交换,这些字符串最终需要满足如下的性质:
对于任意的
i
<
j
<
k
i < j < k
i<j<k,必须有:
l
c
p
(
s
i
,
s
j
)
≤
l
c
p
(
s
i
,
s
k
)
lcp(s_i,s_j)\le lcp(s_i,s_k)
lcp(si,sj)≤lcp(si,sk)以及
l
c
p
(
s
j
,
s
k
)
≤
l
c
p
(
s
i
,
s
k
)
lcp(s_j,s_k)\le lcp(s_i,s_k)
lcp(sj,sk)≤lcp(si,sk)。其中
l
c
p
(
s
,
t
)
lcp(s,t)
lcp(s,t)的定义为:字符串
s
s
s 和
t
t
t 的最长公共前缀的长度。如
l
c
p
(
”
a
b
c
”
,
”
a
b
d
”
)
=
2
lcp(”abc”,”abd”) = 2
lcp(”abc”,”abd”)=2,而
l
c
p
(
”
a
b
c
”
,
”
a
b
c
d
”
)
=
3
lcp(”abc”,”abcd”) = 3
lcp(”abc”,”abcd”)=3。
请按顺序输出你交换了哪些字符串。保证存在一种方案,使得交换之后所有字符串满足上述性质。并且可以证明,在题目给定的范围下,这样的方案一定存在,并且你所需要的最少交换次数不会超过
1
0
6
10^6
106次。
1.2 输入描述
输入文件名为block.in。
第一行为一个正整数
n
n
n,代表字符串的个数。
接下来
n
n
n行,每行一个字符串,代表最初的
s
i
s_i
si。
1.3 输出描述
输出文件名为block.out。
第一行为一个正整数
m
m
m,代表你的交换次数。
接下来
m
m
m行,每行两个正整数
a
,
b
a,b
a,b,代表你交换的两个字符串的编号。
Special Judge将会按顺序完成你给出的交换操作,并判定最后得到的字符串序列是否合法。如果你输出的
m
m
m大于
1
0
6
10^6
106,或者输出格式不正确,将被认为是答案错误。如果你的答案合法并且是正确的,你将会得到对应测试点的得分,反之不得分。
1.4 输入样例&输出样例
block1.in
3
abcd
a
abd
block1.out
1
1 2
另外给出了一个附加样例。
1.5 样例说明
对于第一个样例:
交换后的字符串序列为:
a
,
a
b
c
d
,
a
b
d
a,abcd,abd
a,abcd,abd,不难发现,这是符合要求的。
对于全部的数据,
n
≤
1
0
6
,
∑
∣
s
i
∣
≤
1
0
7
n\le 10^6,\sum |s_i|\le 10^7
n≤106,∑∣si∣≤107,字符串中的所有字符均属于小写英文字母。
思路:
发现建出字典树后,任意一种
d
f
s
序
dfs序
dfs序都满足要求,不妨使它为字典序,直接
s
o
r
t
sort
sort。
关于字典序符合要求的证明:
对于
i
<
j
<
k
i<j<k
i<j<k,字符串
j
j
j必定分别与字符串
i
i
i和
k
k
k的相似度最高。
代码:
#include<bits/stdc++.h>
using namespace std;
#define in Read()
inline int in{
int s=0,f=1;char x;
for(x=getchar();!isdigit(x);x=getchar()) if(x=='-') f=-1;
for( ;isdigit(x);x=getchar()) s=(s<<1)+(s<<3)+(x&15);
return s*f;
}
const int A=1e7+5;
const int B=1e6+5;
int n;
struct Qur{
string ch;
int id;
inline friend bool operator < (const Qur &x,const Qur &y){
return x.ch<y.ch;
}
}p[B];
int ans;
vector <pair<int,int> > q;
signed main(){
n=in;
for(int i=1;i<=n;i++){
cin>>p[i].ch;
p[i].id=i;
}
sort(p+1,p+1+n);
for(int i=1;i<=n;i++){
if(p[i].id==i) continue;
while(p[i].id!=i){
q.push_back(make_pair(i,p[i].id));
swap(p[i],p[p[i].id]);
ans++;
}
}
printf("%d\n",ans);
for(int y=q.end()-q.begin()-1;y>=0;y--)
printf("%d %d\n",q[y].first,q[y].second);
return 0;
}