2017年浙江中医药大学大学生程序设计竞赛(重现赛)C - 寻找zcmu
题目描述
一年一度的浙江中医药大学程序设计校赛正在火热进行,举办至今这是第十一届校赛了。
那么今年就来寻找一下zcmu。
这里有一串只包含小写字母的字符串,里面有若干个zcmu,你为了省力,需要知道最少需要删除几个字符是的有连续四个字符是"zcmu"。
输入描述:
多组数据
每组数据包含一个字符串
1 <= n <= 100000
输出描述:
输出一个整数表示最少需要删除的字符数,若不存在则输出"-1"。
示例1
输入
zcmu umcz zzccmmuuaa
输出
0 -1 2
题解
$dp$。
先处理$z$,然后处理$c$,然后处理$m$,最后处理$u$。每个字母处理的时候计算离得最近的上一种字母。
#include <bits/stdc++.h> using namespace std; const int maxn = 100000 + 10; char s[maxn]; int dp[maxn][4]; int pre[maxn]; int main() { while(~scanf("%s", s)) { for(int i = 0; s[i]; i ++) { for(int j = 0; j < 4; j ++) { dp[i][j] = 200000; } } int pos; //--- z pos = -1; for(int i = 0; s[i]; i ++) { if(s[i] == 'z') { dp[i][0] = i; pos = i; } pre[i] = pos; } //--- c for(int i = 0; s[i]; i ++) { if(s[i] == 'c' && pre[i] != -1) { dp[i][1] = dp[pre[i]][0]; } } pos = -1; for(int i = 0; s[i]; i ++) { if(s[i] == 'c') pos = i; pre[i] = pos; } //--- m for(int i = 0; s[i]; i ++) { if(s[i] == 'm' && pre[i] != -1) { dp[i][2] = dp[pre[i]][1]; } } pos = -1; for(int i = 0; s[i]; i ++) { if(s[i] == 'm') pos = i; pre[i] = pos; } //--- u for(int i = 0; s[i]; i ++) { if(s[i] == 'u' && pre[i] != -1) { dp[i][3] = dp[pre[i]][2]; } } int ans = 200000; for(int i = 0; s[i]; i ++) { if(s[i] == 'u') { if(dp[i][3] != 200000) { ans = min(ans, i - dp[i][3] + 1 - 4); } } } if(ans == 200000) ans = -1; printf("%d\n", ans); } return 0; }