J 严格一致

文章描述了一个关于字符串处理的算法问题,其中小明需要通过特定操作使多个字符串变得相同。解题思路涉及构造循环移位字符串,通过比较和操作找到最小操作次数。程序使用C++编写,通过双重循环枚举基准字符串并计算转换成本。
摘要由CSDN通过智能技术生成

题目描述

小明在太空博物馆发现n个字符串s1,s2,…sn,每个字符串由小写英文字母组成。在一次操作中,他可以选择一个字符串si,抹掉第一个字符并将其附加到字符串的末尾。例如字符串“coolming”,他可以在一次操作中将其转换为字符串“oolmingc”。现在小明想知道:为了将所有字符串变为相同,需要做的最小操作次数是多少?

输入

第一行包含整数n(1 ≤ n ≤ 50)——字符串的数量。之后n行,每行都包含一个字符串。所有字符串的长度相等,不超过50

输出

最小操作的次数,以使所有字符串相等。如果没有解决方案,输出-1。

样例输入

3
abde
bdea
deab

样例输出

3

解题思路

首先对于每个字符串,我们可以构造一个基于第一个字符的循环移位字符串,即将第一个字符移到字符串末尾而得到的字符串。例如,对于字符串“coolming”,我们可以构造如下的循环移位字符串:
coolming
oolmingc
olmingco
lmingcoo
mingcool
ingcoolm
ngcoolmi
gcoolmin
显然,对于每个字符串,我们可以利用如上的方法构造出 n 个循环移位字符串。
然后,我们可以枚举一个基准字符串,假设其为 si,将其转化为 si-0、si-1、si-2、……、si-n-1 这 n 个循环移位字符串。对于每个其它字符串,例如 sj,我们可以在其 n 个循环移位字符串中搜索,找到第一个与 si-0 相同的循环移位字符串,记其为 sj-k,那么将 sj 转化为 sj-k、sj-k+1、sj-k+2、……、sj-k+n-1 这 n 个循环移位字符串所需要的操作数就是 k。
最后,我们求出将所有字符串转化为它们各自的 si-0 所需要的操作数之和,取其中的最小值,即可得到最终的答案。
因此,我们直接双重for循环进行枚举,每次都以第一重for循环的s[i]为基准字符串,计算其他 n - 1个字符串变成基准字符串所需要的操作次数。在每次第二重循环结束之后更新ans值即可。

#include<bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int n;
    cin >> n;
    string s[n];
    for(int i = 0; i < n; i++) cin >> s[i];
    //unordered_map<string, int>mp;
    int ans = INT_MAX;
    bool flag = false;
    for(int i = 0; i < n; i++) {
        //mp[s[i]] = 0;
        int cnt = 0, res = 0;
        for(int j = 0; j < n; j++) {
            if(i == j) continue;
            int sum = 0;
            string str = s[j];
            if(str == s[i]) res++; 
            while(str != s[i]) {
                if(str == s[j] && sum != 0) break;
                str += str[0];
                str = str.erase(0, 1);
                sum++;
                if(str == s[i]) {
                    //mp[str] = sum;
                    res++; // res 用于记录能够经过移动能够和基准字符串s[i]相等的字符串个数
                    cnt += sum;
                }
            }
        }
        if(res == n - 1) {
            flag = true; // 存在解决方案
            ans = min(ans, cnt);
        }
    }
    if(flag) cout << ans;
    else cout << -1;
    return 0;
}
/*
3
abde
bdea
deab
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值