回文子串 manacher方法
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define min(a,b) ( ((a)>(b)) ? (b):(a) )
char * init (char *list,int n)
{
int i;
char *str;
// printf("%d\n",2*n+2);
str = (char *)malloc(2*n+3*sizeof(char));
// printf("%s\n","22");
str[0] = '&';
str[1] = '#';
for(i=0;i<n;i++)
{
str[2*i+2]=list[i];
str[2*i+3]='#';
}
str[2*n+2] = '\0';
//memset(list,0,200);
return str;
}
int get_pre(char * list,int n)
{
int mx=0,idx=0,i,j,p[n],ans=0;
for(i=0;list[i]!='\0';i++)
{
if(mx>i)
{
j = 2*idx-i;
p[i] = min(p[j],mx-i);
}
else
{
p[i] = 1;
}
for(;list[i+p[i]]==list[i-p[i]];p[i]++)
;
if(p[i]+i>mx)
{
mx = i+p[i];
idx = i;
}
}
for(i=0; i<n; i++)
{
if(p[i]>ans)
{
ans = p[i];
}
}
return (ans-1);
}
int main(void)
{
int count,i,max,n;
scanf("%d",&count);
//char * list[count];
char * list,*tmp;
list = (char *)malloc(200*sizeof(char));
//list = (char *)malloc(201*sizeof(char));
for(i=0;i<count;i++)
{
scanf("%s",list);
n = strlen(list);
tmp = init(list,n);
printf("%s\n",tmp);
max=get_pre(tmp,2*n+2);
memset(tmp,0,2*n+2);
//free(tmp);
printf("%d\n",max);
}
}
问题
1.宏的优缺点
宏会在编译器在对源代码进行编译的时候进行简单替换,不会进行任何逻辑检测,即简单代码复制而已,既然是单纯的替换,如果你括号去掉由于优先级的关系,就有可能出现问题。之所以用宏是因为 宏的效率高,不需要压栈 和出栈
2.指针,动态申请的空间.就不要使用sizeof(s)了。因为sizeof(s)的结果是4.
3.
4.特殊字符 '' '\n' '\0' 特殊数字 0 负数
5.C:char a[]ok char[]a wrong
6.如果数组定义在函数内,生命周期应该是在函数内部,会被分配在内存栈中,在函数调用完毕时,系统会自动释放栈内资源。
函数的返回值存储在寄存器或者栈中
char * Get()
{
char *pp = "hello";
return pp;
}
void main()
{
char * p = NULL;
p = Get();
printf("%s\n",p);
}
会输出hello 因为 hello是常量,在常量区有效期为整个程序
pp是指针存储在了栈中 所以之后还是指向hello常量
但是,当一个字符常量串被用来为数组初始化的时候,那么该字符串常量将不会放入常量区,而是放入对应的数组中
所以如果char[20]p 程序就有问题
7.malloc分配的内存在堆栈中 使用完毕后需手动释放 则会造成严重的内存泄漏,直到该进程退出后才会被操作系统回收
8.char [22]x;
x="sss";//错误 C++ forbids assignment of arrays
数组不同于char *,数组的话只能进行内存数组的拷贝
9.char *a;
a="22222";//a指向常量区
10.char a[5]="1234";//ok
char a[5]="12345"//wrong
字符数组会在最后一位自动补全“\0”,数组大小比字符串长度至少要大一个
指针动态malloc地址时,不会自动补全 所以要手动在最后一位加"\0"
11.程序的字符串的第一个地址开始,读取字符,然后输出,直到遇到\0字符,就结束了。如果没有\0,序就认为没有结束,继续往下读,数组里的编码可能不是字符,所以输出就是乱码了。直到遇到内存中不知哪里的\0或是数组结束了,程序才结束。
(字符数组逐个赋值时需要注意)
12.存储分配问题的三种方式:
1.直接指定方式:程序员在编程序时,或编译程序(汇编程序)对源程序进行编译(汇编)时,使用实际存储地址。
2.静态分配方式(Static Allocation ,存储分配是在装入时实现的
3.动态分配方式(Dynamic Allocation):
动态分配是一种更加有效的使用主存储器的方法。
这种动态存储分配方式的特点是:
(1)作业在存储空间中的位置,也是在其装入时确定的;
(2)在其执行过程中可根据需要申请附加的存储空间;
(3)一个作业已占用的部分存储区域不再需要时,可以要求归还给系统。
(4)存储区域的大小是可变的;
(5)允许作业在内存中“搬家”
12.指针在编译后直接转化为变量所在地址
13.为指针分配一块空间,c并不会记录指针和地址对应关系。而只是记录哪些内存被使用(如段页式存储记录)。至于哪些地址空间是自己的,需要程序员自己管理。
14.栈区的执行效率高于堆区,so 指针malloc<数组。栈的空间一般为2M,分配太多栈空间程序会崩溃
15.只有全局变量或者static变量会初始化为0
16.free完malloc的地址要将其置为NULL不然还是指向原来的堆,造成堆破坏