Many modern text editors automatically check the spelling of the user's text. Some editors even suggest how to correct typos.
In this problem your task to implement a small functionality to correct two types of typos in a word. We will assume that three identical letters together is a typo (for example, word "helllo" contains a typo). Besides, a couple of identical letters immediately followed by another couple of identical letters is a typo too (for example, words "helloo" and "wwaatt" contain typos).
Write a code that deletes the minimum number of letters from a word, correcting described typos in the word. You are allowed to delete letters from both ends and from the middle of the word.
The single line of the input contains word s, its length is from 1 to 200000 characters. The given word s consists of lowercase English letters.
Print such word t that it doesn't contain any typos described in the problem statement and is obtained from s by deleting the least number of letters.
If there are multiple solutions, print any of them.
helloo
hello
woooooow
woow
The second valid answer to the test from the statement is "heloo".
一个字符串,不能有连续三个一样的,也不能有连续两个两个一样的,比如“aaoo"。这个就是模拟其实,对于连续三个的,删掉一个就好;对于第二种情况,优先删除后面的,因为这样可以保证最少的删除数。于是我想到了erase,刚学的装逼函数怎么可以不用?然后数组不断越界- -,最后发现可以用len先储存长度,然后如果删除了,就len--;在各个删除判断中加上长度的判断,终于……超时了。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<string>
using namespace std;
string c = "";
int main()
{
int i, j, m, n, ans, len;
cin >> c;
len = c.size();
for (i = 0; i < len; i++){
if (i <= len - 3){
while (c[i] == c[i + 1] && c[i + 1] == c[i + 2] && i <= len - 3)
{
c.erase(i, 1);
len--;
if (i>len - 3)break;
}
}
if (i <= len - 4){
while (c[i] == c[i + 1] && c[i + 2] == c[i + 3] && i <= len - 4)
{
c.erase(i + 2, 1);
len = len - 1;
if (i > len - 4)break;
}
}
}
cout << c;
return 0;
}
然后我才知道,erase这个函数是删除这个位置的字符,然后把后面的字符一次向前推进,这他么复杂度不是要逆天。只好手动写标记数组。不符合leap[i]=1;符合就是leap[i]=0;这样就可以输出了。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<string>
using namespace std;
char c[200005], leap[200005];
int main()
{
int i, j, m, n, ans, len, pre;
char temp1, temp2, temp3, temp4;
scanf("%s", c);
memset(leap, 0, sizeof(leap));
len = strlen(c);
for (i = 0; i < len - 2; i++)
{
temp1 = c[i]; temp2 = c[i + 1]; temp3 = c[i + 2];
if (temp1 == temp2&&temp1 == temp3)
{
leap[i] = 1; continue;
}
else if (i <= len - 4)
{
temp4 = c[i + 3];
j = 2; pre = 0;
while(temp1 == temp2&&temp3 == temp4)
{
leap[i + j] = 1;
j++; pre = 1;
if (i + j + 1 < len)
{
temp3 = c[i + j];
temp4 = c[i + j + 1];
}
else break;
}
if (pre)
i = i + j;
}
}
for (i = 0; i < len; i++)
{
if (!leap[i])
cout << c[i];
}
return 0;
}
然后看了一下小伙伴的代码,是先吧3个以上排除掉。其实我在第二步也想这样实现,但是如果这么做,就会导致赋值temp1,temp2,temp3,无比麻烦,因此采用规矩的模拟。小伙伴是用string和一个leap判断搞定的第一步,然后再搞定第二步,虽然和第二种思路一样,但是时间快了一倍。
#include<cstdio>
#include<queue>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<string>
#include<iomanip>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const int inf = 0x3f3f3f3f;
const int maxn = 2e6 + 15;
int N, k;
string s, ans, temp;
int main(){
ios::sync_with_stdio(false);
cin >> s;
int cnt = 1;
temp += s[0];
for(int i = 1; i < s.size(); i++){
if(s[i] == s[i - 1]){
cnt++;
if(cnt <= 2)
temp += s[i];
}
else{
cnt = 1;
temp += s[i];
}
}
// cout << temp << endl;
cnt = 0;
ans += temp[0];
for(int i = 1; i < temp.size(); i++){
if(temp[i] == temp[i - 1])
cnt++;
else if(i + 1 != temp.size() && temp[i] == temp[i + 1] && cnt == 1){
ans += temp[i];
i++;
cnt = 0;
continue;
}
else if(temp[i] != temp[i - 1])
cnt = 0;
ans += temp[i];
}
cout << ans << endl;
return 0;
}
虽然也有很多人是用这个数位的方法写,但是我觉得这个写的是最清晰,思路明了的代码。