传送门:
[1]:HDU
[2]:bestcoder
B.度度熊与排列(思维)
•题意
有一个数组 p,p 中包含的数为 1~m 的全排列,一个含 m 个字符的串 s;
在 s 上有一个操作,对于 s 中的第 i 个位置的字符,放到 p[ i ] 位置,构成一个新串 t;
即 $s_{i}=t_{p_i}$;
给你 2n 个串,每两个串为一组,前一个串表示原串 s,后一个串表示经过 p 映射后的新串 t;
求是否存在某个 1~m 的全排列,使得这 n 组串都可以经过 p 由 s 变为 t;
如果存在,输出字典序最小的那组,如果不存在,输出 -1;
•题解
$S=egin{bmatrix} s_1: & s_{11} & s_{12} & cdots & s_{1m} \ s_2: & s_{21} & s_{22} & cdots & s_{2m} \ s_3: & s_{31} & s_{32} & cdots & s_{3m} \ vdots & vdots & vdots & vdots vdots & vdots \s_n: & s_{n1} & s_{n2} & cdots & s_{nm} end{bmatrix} underrightarrow {p} egin{bmatrix} t_1: & t_{11} & t_{12} & cdots & t_{1m} \ t_2: & t_{21} & t_{22} & cdots & t_{2m} \ t_3: & t_{31} & t_{32} & cdots & t_{3m} \ vdots & vdots & vdots & vdots vdots & vdots \t_n: & t_{n1} & t_{n2} & cdots & t_{nm} end{bmatrix}=T$
$s_{i,j} underrightarrow {p} t_{i,p_j}$;
对于 S 中的第 j 列,经过映射变成 T 中的第 pj 列;
可以将 S,T 中的各个列以字符串的形式存下来;
对于 Sj ,判断 T 中是否存在未被标记 Sj,如果存在,找出字典序最小的那个对应过去即可,并标记;
如果不存在,输出 -1;
•Code
O(n·m)1 #include<bits/stdc++.h> 2 using namespace std; 3 #define fi first 4 #define se second 5 const int maxn=60; 6 7 int n,m; 8 char s[maxn]; 9 int ans[maxn]; 10 pair<string ,int >f[maxn],g[maxn]; 11 12 void Solve() 13 { 14 ///f,g分别拍完序后,第i个的first要对应才有解 15 for(int i=1;i <= m;++i) 16 if(f[i].fi != g[i].fi) 17 return puts("-1"),void(0); 18 19 for(int i=1;i <= m;++i) 20 ans[f[i].se]=g[i].se; 21 22 for(int i=1;i <= m;++i) 23 printf("%d%c",ans[i],i == m ? ' ':' '); 24 } 25 int main() 26 { 27 int T; 28 scanf("%d",&T); 29 while(T--) 30 { 31 scanf("%d%d",&n,&m); 32 33 for(int i=1;i <= m;++i) 34 f[i]=g[i]=make_pair("",i); 35 36 for(int i=1;i <= n;++i) 37 { 38 scanf("%s",s+1); 39 for(int j=1;j <= m;++j) 40 f[j].fi += s[j]; 41 42 scanf("%s",s+1); 43 for(int j=1;j <= m;++j) 44 g[j].fi += s[j]; 45 } 46 47 sort(f+1,f+m+1); 48 sort(g+1,g+m+1); 49 50 Solve(); 51 } 52 return 0; 53 }
•感想
比赛的时候搜索,TLE,并未想到如果 S 中的第 j 列在 T 中找到一个满足的时候就找到当前 j 的对应列;
并且以后在查找的时候,之前找到的列并不影响答案的正确性,由此衍生出了 O(n·m2) 的解法;
而上述解法是在参阅了 rank1 的代码后提取出的思路,tql;
O(n·m),字符串哈希1 #include<bits/stdc++.h> 2 #define For(i,j,k) for (int i=(int)(j);i<=(int)(k);i++) 3 #define Rep(i,j,k) for (int i=(int)(j);i>=(int)(k);i--) 4 #define pii pair<int,int> 5 #define pll pair<ll,ll> 6 #define ll long long 7 #define fi first 8 #define se second 9 #define PB push_back 10 #define uint unsigned 11 #define ull unsigned ll 12 using namespace std; 13 pll hsh1[55],hsh2[55]; 14 int n,m,ans[55]; 15 char s[55]; 16 void solve(){ 17 scanf("%d%d",&n,&m); 18 For(i,1,m) hsh1[i]=hsh2[i]=pll(0,i); 19 For(i,1,n){ 20 scanf("%s",s+1); 21 For(j,1,m) hsh1[j].fi=hsh1[j].fi*233+s[j]; 22 scanf("%s",s+1); 23 For(j,1,m) hsh2[j].fi=hsh2[j].fi*233+s[j]; 24 } 25 sort(hsh1+1,hsh1+m+1); 26 sort(hsh2+1,hsh2+m+1); 27 For(i,1,m) 28 if (hsh1[i].fi!=hsh2[i].fi) 29 return puts("-1"),void(0); 30 For(i,1,m) 31 ans[hsh1[i].se]=hsh2[i].se; 32 For(i,1,m) printf("%d%c",ans[i],i==m?' ':' '); 33 } 34 int main(){ 35 int T; 36 scanf("%d",&T); 37 while (T--) solve(); 38 }