Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 删除任何“;配对;字符串中具有相同值的相邻字母的_C++_String_Optimization_Micro Optimization - Fatal编程技术网

C++ 删除任何“;配对;字符串中具有相同值的相邻字母的

C++ 删除任何“;配对;字符串中具有相同值的相邻字母的,c++,string,optimization,micro-optimization,C++,String,Optimization,Micro Optimization,比如说- aaabccddd->abd aaacccbbcccd->accd->ad 阿巴->空刺 我首先尝试了下面的方法。调用splitString函数直到字符串无法进一步缩减(即,我们提供的字符串长度(a)=执行操作后获得的字符串长度)。 对于10^5左右的值,此代码给出超出内存限制(MLE)错误,但是对于小于10^5的值运行正常。 #include<bits/stdc++.h> using namespace std; void splitString(string str)

比如说-

aaabccddd->abd

aaacccbbcccd->accd->ad

阿巴->空刺

我首先尝试了下面的方法。调用splitString函数直到字符串无法进一步缩减(即,我们提供的字符串长度(a)=执行操作后获得的字符串长度)。 对于10^5左右的值,此代码给出超出内存限制(MLE)错误,但是对于小于10^5的值运行正常。

#include<bits/stdc++.h>
using namespace std;

void splitString(string str)
{
    int a=str.length();
    for(int i=0; i<str.length()-1; i++)
    {
        if(str[i]==str[i+1]){str[i]=1; str[i+1]=1;}
    }

    string alpha="";
    for (int i=0; i<str.length(); i++)
    {
        if(str[i] >= 'a' && str[i] <= 'z')
            alpha.push_back(str[i]);
    }

    int b=alpha.length();
    if(a==b)
    {cout <<b<<"\n"<<alpha; return;}
    else
    {splitString(alpha);}

}

int main()
{
    int n; string str; cin>>n>>str;

    splitString(str);

    return 0;
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define size 100005

void foo(char *s){
    int len = strlen(s);
    int i, j;
    j = 0;
    for(i = 0; i < len; i++)
    {
        if(s[i] != '$')
        {
        s[j] = s[i]; j++;
        }
    }
    s[j] = '\0';
}
char* super_reduced_string(char* s){
    int len = strlen(s);
    int i;
    for(i = 1; i < len; i++){
        if(s[i] == s[i-1])
        {
            s[i] = s[i-1] = '$';
            foo(s);
            len = strlen(s);
            i = 0;
        }
    }
    return s;
}

int main() {
    int n; scanf("%d", &n);
    char s[size]={0};
    scanf("%s", s);
    char* result = super_reduced_string(s);

        printf("%d", strlen(result));
        printf("\n");
        printf("%s\n", result);
    return 0;
}
#包括
使用名称空间std;
空拆分字符串(字符串str)
{
int a=str.length();

对于(int i=0;i您可以对当前算法进行一些改进,例如直接删除字符而不将
'$'
存储为填充符。例如,执行一次就地对删除过程(如第二个版本,但在第一对之后不停止),然后重复,直到长度停止更改。(在循环中而不是尾部递归中)

但实际上,不同的算法更有意义

这可能是就地(O(1)存储,在单次(O(n)时间内,常数因子较低,在为现代x86编译时,每个字节可能有几个到几个时钟周期。分支预测失误可能是最大的变量

这看起来像是一个现有的在线问题。 。您可以查看现有的解决方案,如(并且可以看到,许多解决方案都像垃圾一样编码,带有全局变量和1个字母的变量名,并且
i
,每次迭代都会重新运行
strlen
),但我查看的2的实际算法是好的(除了循环中的strlen使其成为O(n^2),并证实了我的想法,即如果你能够在折叠一系列对之后继续回溯,那么就有可能在间隔前后的奇数字母之间创建一个新的对。也就是说,你可以回溯并再次查看将成为输出一部分的字母

我的版本针对可能有3个或更多相同字符的输入进行了优化,不仅仅是分散的对,但在这种情况下也可以

为了对回溯字符串开头的检查进行微优化,实际字符串数据位于一个具有前导
0
字节(
'\0'
字符)的缓冲区中。这意味着我们不需要在
buf[wpos-1]==c
之前检查
wpos!=0

黑客竞赛/练习网站将此列在“堆栈”练习下。您可以将写入位置视为堆栈。

#include<bits/stdc++.h>
using namespace std;

void splitString(string str)
{
    int a=str.length();
    for(int i=0; i<str.length()-1; i++)
    {
        if(str[i]==str[i+1]){str[i]=1; str[i+1]=1;}
    }

    string alpha="";
    for (int i=0; i<str.length(); i++)
    {
        if(str[i] >= 'a' && str[i] <= 'z')
            alpha.push_back(str[i]);
    }

    int b=alpha.length();
    if(a==b)
    {cout <<b<<"\n"<<alpha; return;}
    else
    {splitString(alpha);}

}

int main()
{
    int n; string str; cin>>n>>str;

    splitString(str);

    return 0;
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define size 100005

void foo(char *s){
    int len = strlen(s);
    int i, j;
    j = 0;
    for(i = 0; i < len; i++)
    {
        if(s[i] != '$')
        {
        s[j] = s[i]; j++;
        }
    }
    s[j] = '\0';
}
char* super_reduced_string(char* s){
    int len = strlen(s);
    int i;
    for(i = 1; i < len; i++){
        if(s[i] == s[i-1])
        {
            s[i] = s[i-1] = '$';
            foo(s);
            len = strlen(s);
            i = 0;
        }
    }
    return s;
}

int main() {
    int n; scanf("%d", &n);
    char s[size]={0};
    scanf("%s", s);
    char* result = super_reduced_string(s);

        printf("%d", strlen(result));
        printf("\n");
        printf("%s\n", result);
    return 0;
}
//这是我的版本。不要在在线比赛中作为你的版本提交。
//但是可以在其他任何地方使用它。对于这个答案的代码部分,license=公共域。
#包括
#包括
#包括
#包括
#包括
//第一次不匹配=一次跑步结束后一次
内联大小查找不到(常量字符*基数、大小位置、字符指针){
while(基[pos]==针){
pos++;
}
返回pos;
}
静态字符static_buf[10000002];
int main(int argc,char*argv[])
{
char*buf=static_buf+1;
int infd=0;
如果(argc>1)infd=open(argv[1],Ordonly);
//尺寸长度=
read(infd,buf,sizeof(static_buf)-4);//修复:不处理短读
//1字节的开头填充不能出现在字符串中的值可以简化回溯
//我认为我们的读数不会超过结尾;c!=0,所以检查该值的运行不会走得太远。
//static_buf[0]=0;//str[-1]
//str[len]=0;
大小\u t RPO=0;
while(buf[rpos]&&buf[rpos]!=buf[rpos+1])//std::nexting\u find
rpos++;
//只读,直到第一对或字符串结束。是否可以使用类似palignr的字节移位来SIMD它以馈送pcmpeqb
如果(buf[RPO]){
//我们很早就停了下来,一对一对
size\u t wpos=rpos;//下一个写入位置。prev char=字符串前的0,或最后一个非对
rpos+=2;//从对后读取
//rpos=find_not(buf,rpos+2,buf[rpos]);//运行后读取
//wpos+=(RPO-(wpos+1))%2;//奇数运行长度->保留一个,否则为0
字符c;
而((c=buf[RPO])!=0){
大小\u t运行\u结束=查找\u未(基本单位,RPO+1,c);
如果((运行结束-RPO)%2){
//读端留下一个字符,写端是否取消。
if(buf[wpos-1]==c)//字符串开头之前的0总是比较false
--WPO;
其他的
buf[wpos++]=c;
}
rpos=运行结束;
}
buf[wpos]=0;
}//否则我们将命中一个终止的0,但找不到一对
puts(buf[0]?buf:“空字符串”);
如果(infd==0)
lseek(infd,0,SEEK_SET);//倒带stdin,以便在perf stat下重新读取另一次运行
}
假设一个
read
将读取所有可用的输入不是一个好主意。它可能不会,例如从管道中。我使用POSIX
read
而不是stdio
fread
,因为我想我将使用长度而不是调用
strlen
。stdio行输入函数大多是哑的,不会返回他们刚刚找到的线路长度

GCC的另一个微观优化是将
(run_end-rpos)%2
编写为
(run_end+rpos)%2
。GCC知道未签名的
%2
只取低位,但它没有意识到当您只需要低位时,可以添加、SUB和XOR(添加而不带进位)它们都是等价的,只是在高位不同,进位/借位/无从低位传播。
+
是可交换的,可以在x86上使用LEA指令进行复制和添加。在这种特殊情况下,它恰好在
周围保存2条
mov
指令,而只是