Codeforces 798B 字符串暴力

传送门:题目

题意:

n个字符串,每个字符串都可以做一个操作:字符串的第一位移到字符串的末尾,剩下的字符向前进一位,问最少做多少次操作,所有字符串能相等。

题解:

第一开始我想到的是纯模拟,模拟字符串向前移动的过程,然后 n2 n 2 搜索最优解,不知不觉写了5for循环,算了一下复杂度 505=109 50 5 = 10 9 ,心想肯定T了,然后交了一下,看看能不能卡过去,竟然跑了 30ms 30 m s AC了,果然数据很水,赛后看题解,发现一种巧妙的办法,就是把字符串×2倍,然后找子串,这样的复杂度是 O(n2+log2n) O ( n 2 + log 2 ⁡ n ) ,方法很好记录一下。

AC代码:(纯模拟)

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define debug(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
using namespace std;

int cnt = 0, ans = INF, n;
string str[55], ori[55];
void init() {
    for (int i = 0; i < n; i++)
        str[i] = ori[i];
}
void frontstep1(string& a) {
    a += *a.begin();
    a.erase(0, 1);
}
bool check(string a, string b) {
    return a == b;
}
int main(void) {
    cin >> n;
    for (int i = 0; i < n; i++)
        cin >> str[i], ori[i] = str[i];
    for (int i = 0; i < n; i++) {
        init();
        cnt = 0;
        for (int j = 0; j < n; j++) {
            if (j == i)
                continue;
            for (int k = 0; k < 55; k++) {
                if(k==54)
                    return 0 * puts("-1");
                if (check(str[j], ori[i]))
                    break;
                frontstep1(str[j]);
                cnt++;
            }      
        }
        ans=min(ans,cnt);
    }
    cout<<ans<<endl;
    return 0;
}

AC代码:(字符串拼接找子串)

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define debug(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
using namespace std;

int main(void){
    int mmin=INF,n,index;
    string str[60];
    cin>>n;
    for(int i=0;i<n;i++)    
        cin>>str[i];
    for(int i=0;i<n;i++){
        int sum=0;
        for(int j=0;j<n;j++){
            index=(str[j]+str[j]).find(str[i]);
            index==(int)string::npos?sum=-1:sum+=index;
        }
        mmin=min(mmin,sum);
    }
    cout<<mmin<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值