Codeforces Round #732 (Div. 2) B. AquaMoon and Stolen String 题解

B. AquaMoon and Stolen String

题意

给定t组n,m
( t组n*m的总和 <= 1e5 )
接下来n行
n个长度为m的字符串

对于每一对字符串,假设为s[i]和s[j]
你都可以选择一些位置(至少1个,最多m个)
并在所选位置交换这一对的两个字符串中的字母。
即swap(s[i][k],s[j][k]) 
 [ 1 <= i <= n , 1 <= j <= n , 1 <= k <= m ]

接下来n-1行
n-1个长度为m的字符串

问你
一定可以进行一些交换
使得这n-1个字符串等于
一开始给的n个字符串中的其中n-1个
并且输出剩下的那一个字符串

思路

个人感觉这题理解题意是其一

那么考虑一下交换
只在不同对之间的不同位置交换
即swap(s[i][k],s[j][k])  [ 1 <= i <= n , 1 <= j <= n , 1 <= k <= n ]
即只有列之间的字母交换
但是列之间不管怎么交换
每一列对应的字母个数是不变的

所以最后的答案等于

每一列前n个字符串
和最后n-1个字符串作比较
所缺少的那一个字符相加

考虑一下一共26个字母
对每一列统计字母个数
一共n行,m列

用map方便统计

所以总体时间复杂度为 n * m * log26 + m * 26 * log26

时间复杂度:O n

#include<bits/stdc++.h>
#define fer(i,a,b) for(re i = a ; i <= b ; ++ i)
#define re register int
#define pll pair<int,int> 
#define x first 
#define y second 
#define sf(x) scanf("%d",&x)
#define sfl(x) scanf("%lld",&x)
typedef long long ll ;
using namespace std;
const int N =  1e5 + 10 , M = 1010 , inf = 0x3f3f3f3f , mod = 1e9 + 7 ;
int n , m ;
map<char,int> q1[N] , q2[N] ;
int main()
{
    int t  ;
    cin >> t ;
    
    while(t--)
    {
        cin >> n >> m ; 
        
        fer(i,1,m) q1[i].clear() , q2[i].clear() ;
        
        fer(i,1,n)
        {
            fer(j,1,m)
            {
                char x ;
                cin >> x ;
                q1[j][x] ++ ;  // j这列x的字母个数++
            }
        }
        
        fer(i,1,n-1)
        {
            fer(j,1,m)
            {
                char x ;
                cin >> x ;
                q2[j][x] ++ ;  // j这列x的字母个数++
            }
        }
        
        string res = "" ;
        
        for(int i = 1 ; i <= m ; i ++)
        {
            for(char j = 'a' ; j <= 'z' ; j ++)
            {
                if(q1[i][j] - q2[i][j] == 1)
                {
                    res += j ;
                    break ;
                }
            }
        }
        
        cout << res << "\n" ;
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值