Educational Codeforces Round 40 (Rated for Div. 2)

A. Diagonal Walking

简单模拟

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>

using namespace std;

int n;
char s[110];
vector<char> G;

int main(){
    scanf("%d", &n);
    scanf("%s", s+1);
    int i = 1;
    while(i<=n){
        if((s[i] == 'U' && s[i+1] == 'R') || (s[i] == 'R' && s[i+1] == 'U')){
            G.push_back('D');
            i+=2;
        }
        else{
            G.push_back(s[i]);
            i++;
        }
    }

    printf("%d\n", G.size());

    return 0;
}

 B. String Typing(kmp)

题意:有两种操作,往一个字符串末尾添加一个字符,可以操作无限次;将当前字符复制一遍,最多操作一次。现给出一个字符串,问最少操作多少步能够得到该字符串。

题解:首先求出next数组和最小循环节,从后往前找,若某一个前缀出现了多k次该循环节,那么最优的做法一定是先单个添加k/2个循环节,然后复制一遍,然后剩下的再单个添加。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>

using namespace std;

int n;
char s[220];
int nxt[220];

void getnxt(){
    nxt[0] = -1;
    int i = 0, j = -1;
    while(i<n){
        if(j == -1 || s[i] == s[j]){
            i++; j++;
            nxt[i] = j;
        }
        else{
            j = nxt[j];
        }
    }
}

int main(){
    scanf("%d", &n);
    scanf("%s", s);
    getnxt();

    int len = 0;
    int ans = 0;
    int k = 0;

    for(int i = n; i>=0; i--){
        int t = i-nxt[i];
        if(i%t == 0 && i/t>1){
            len = t;
            k = i/t;
            break;
        }
    }
    if(len!=0){
        ans+=len*(k/2);
        ans++;
        ans+=len*(k-2*(k/2));
        ans+=n-len*k;
    }
    else{
        ans = n;
    }
    printf("%d\n", ans);

    return 0;
}

猜你喜欢

转载自www.cnblogs.com/grimcake/p/9845633.html
今日推荐