360编程题 偶串 题意:
一个字符串所有字符出现次数都是偶数,则称它为偶串。
现在给你一个字符串,你需要输出该字符串中包含多少偶串。这里的字串必须是原串中连续的一段。
比如一个n长度的字符串有n*(n+1)/2个字串
可以用状态压缩的方式写
#include <bits/stdc++.h> #define maxn 100009 using namespace std; char s[maxn]; map<int,int>mp; int n; int main(){ scanf("%s",s); n = strlen(s); mp[0] = 1; int cur = 0; long long ans = 0; for(int i = 0; i < n; i++){ int x = s[i] - 'a'; cur ^= (1 << x); ans += mp[cur]; mp[cur]++; } cout << ans << endl; return 0; }
mp[cur]的值是一系列的等差数列,因为 最后的答案肯定是一些等差数列的和的。。这个方法是真的巧妙哇
它用位运算存储当前状态,如果有状态重复出现就累加,其实是非常简单的状态压缩
然后是遇到的一些奇葩问题
1.指针占几个字节?
32位系统占4字节,64位系统占8字节。诸如此类的还有double占8个字节,long long占8个字节,short int占2个字节
2.栈和堆的区别?
这算是一个大类的问题
一个由c/c++编译的程序占用的内存分为以下几个部分:
1.栈区(stack) 由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈
2.堆区(heap)由程序员分配释放,若不释放,程序结束时可能由os回收。它的分配方式类似于链表(这不是数据结构中的堆)
3.全局区(静态区)(static)
一,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域
二,程序结束后由系统释放
4.文字常量区,程序结束后由系统释放
5.程序代码区-存放函数体的二进制代码
嘛,这里还有前辈总结的代码:
//main.cpp
int a = 0; 全局初始化区
char *p1; 全局未初始化区
main()
{
int b; 栈
char s[] = "abc"; 栈
char *p2; 栈
char *p3 = "123456"; 123456/0在常量区,p3在栈上。
static int c =0; 全局(静态)初始化区
p1 = (char *)malloc(10);
p2 = (char *)malloc(20);
分配得来得10和20字节的区域就在堆区。
strcpy(p1, "123456"); 123456/0放在常量区,编译器可能会将它与p3所指向的"123456"
优化成一个地方。
}
申请后系统的响应:
栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出
堆:操作系统有一个记录空闲内存地址的链表,当系统收到程序申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。另外对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。由于找到的堆结点大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中
内存大小:
栈:windows下是个常数,大概开一个int[1000000]的数组就会爆炸,不过c++中提供了方式在编译的时候手动开栈,这个方法可以强行水过一些题
堆:是向高地址拓展的数据结构,是不连续的内存区域。由低地址到高地址
申请效率比较:
栈由系统自动分配,速度较快,程序员无法控制(??可以手动开栈啊,这里应该是说分配过程无法控制吧。。)
堆是new()出来的内存,速度较慢方便,容易产生内存碎片
在windows下有virtualAlloc分配内存的方式,它不是堆也不是栈,是直接在进程的地址空间中保留的一块内存,最快最灵活
效率比较:
char s1[] = "aaaaaaaaaaaaaaa";
char *s2 = "bbbbbbbbbbbbbbbbb";
aaaaaaaaaaa是在运行时刻赋值的;
而bbbbbbbbbbb是在编译时就确定的;
但是,在以后的存取中,在栈上的数组比指针所指向的字符串(例如堆)快。
比如:
#include
void main()
{
char a = 1;
char c[] = "1234567890";
char *p ="1234567890";
a = c[1];
a = p[1];
return;
}
对应的汇编代码
10: a = c[1];
00401067 8A 4D F1 mov cl,byte ptr [ebp-0Fh]
0040106A 88 4D FC mov byte ptr [ebp-4],cl
11: a = p[1];
0040106D 8B 55 EC mov edx,dword ptr [ebp-14h]
00401070 8A 42 01 mov al,byte ptr [edx+1]
00401073 88 45 FC mov byte ptr [ebp-4],al
第一种在读取时直接就把字符串中的元素读到寄存器cl中,而第二种则要先把指针值读到
edx中,再根据edx读取字符,显然慢了。
嘛,大概就是栈比堆块的意思拉
3.哪些运算符可以重载,哪些不能重载
大部分是可以重载的,除了作用域操作符 ::,条件操作符?:,点操作符. ,指向成员操作的指针操作符 ->* ,.* ,预处理符号 #
4.构造函数的执行顺序
顺便说一下构造函数的几个特点:
构造函数不能有返回值。
缺省构造函数时,系统将自动调用该缺省构造函数初始化对象,缺省构造函数会将所有数据成员都初始化为零或空
创建一个对象时,系统自动调用构造函数
然后就是几个顺序:
然后对象是由底向上构造的,先调用基类构造函数再调用下一个派生类构造函数;
成员类对象构造函数如果有多个成员类对象则构造函数的调用顺序是对象在类中被声明的顺序而不是它们出现在成员初始化表中的顺序;
基类构造函数如果有多个基类则构造函数的调用顺序是某类在类派生表中出现的顺序而不是它们在成员初始化表中的顺序;
如果类里面有成员类,成员类的构造函数优先被调用;