k_over 重叠字符串

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string.h>
using namespace std;
#define maxn 1024
#define maxm 1024


int bufa[maxn],bufb[maxn],bufs[maxm],bufv[maxn];
int sa[maxn],height[maxn],rank[maxn];


int cmp(int *src,int a,int b,int l){
return src[a]==src[b]&&src[a+l]==src[b+l];
}
void da(int *src,int n,int m)
{
int i,*x=bufa,*y=bufb,*t;
for(i=0;i<m;i++)   bufs[i]=0;
for(i=0;i<n;i++)   bufs[x[i]=src[i]]++;
for(i=1;i<m;i++)   bufs[i]+=bufs[i-1];
for(i=n-1;i>=0;i--)sa[--bufs[x[i]]]=i;


int p=0,j;
for(j=1,p=1;p<n;j*=2,m=p)
{
for(p=0,i=n-j;i<n;i++) y[p++]=i;
for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;


for(i=0;i<n;i++) bufv[i]=x[y[i]];

for(i=0;i<m;i++) bufs[i]=0;
for(i=0;i<n;i++) bufs[bufv[i]]++;
for(i=1;i<m;i++) bufs[i]+=bufs[i-1];
for(i=n-1;i>=0;i--) sa[--bufs[bufv[i]]]=y[i];


for(t=x,x=y,y=t,i=1,p=1,x[sa[0]]=0;i<n;i++)
 x[sa[i]]=cmp(y,sa[i],sa[i-1],j)? p-1:p++;
}
}


void cal_height(int *src,int n)
{
int i,k,j;
for(i=1;i<n;++i) rank[sa[i]]=i;
for(i=0,k=0;i<n;height[rank[i++]]=k)
 for(k? k--:0,j=sa[rank[i]-1];src[i+k]==src[j+k];k++)
;
}


int RMQ[maxn],mm[maxn];
int best[20][maxn];


void initRMQ(int n)
{
int i,j,a,b;
for(mm[0]=-1,i=1;i<n;i++)
 mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1];
for(i=1;i<n;i++) best[0][i]=i;
for(i=1;i<=mm[n-1];i++)
 for(j=1;j<n-(1<<i)+1;j++){
a=best[i-1][j];
b=best[i-1][j+(1<<(i-1))];
best[i][j]=RMQ[a]>RMQ[b]? a:b;
 }
}


int askRMQ(int a,int b)
{
int t;
t=mm[b-a+1]; b-=((1<<t)-1);
a=best[t][a];
b=best[t][b];
return RMQ[a]>RMQ[b] ? sa[a-1]:sa[b-1];
}


int abs(int n) { return n<0? -n:n;}


int check(int n)
{
int test=(n-1)/2,i;
int max=0,min=0x7fffffff;
for(;test>0;test--){
printf("test=%d\n", test);
for(i=1;i<n;i++)
 if(height[i]>=test){
if(sa[i-1]>max) max=sa[i-1];
if(sa[i]>max) max=sa[i];
if(sa[i-1]<min) min=sa[i-1];
if(sa[i]<min) min=sa[i];
if(max-min>=test)
 return test;
 }
 else 
max=0;
}
return test;
}


int main()
{
char src[maxn],c;
int nsrc[maxn];
int i=0,n;
bzero(src,sizeof(src));
while((c=getchar())!='\n') src[i++]=c;
n=strlen(src);
for(i=0;i<n;i++) nsrc[i]=src[i];
nsrc[n++]=0;


da(nsrc,n,1024);
cal_height(nsrc,n);


for(i=1;i<n;i++) RMQ[i]=height[i];


initRMQ(n);


for(i=1;i<n;i++) printf("%d--> %d\n",i,height[i]);puts("");
for(i=1;i<n;i++) printf("%d\n", sa[i]-sa[i-1]);
for(i=0;i<n;i++) printf("%s\n",src+sa[i]);


printf("%d\n",check(n));





// printf("max len lapped substr:\n");
// int pos=askRMQ(1,n-1);
// int slen=RMQ[rank[pos]+1];
// printf("slen=%d\n",slen);
// printf("pos=%d\n",pos);
// *(src+pos+slen)=0;
// printf("%s\n",src+pos);

}
### 字符数组与字符串的内存占用及容量比较 #### 1. 字符数组的内存占用 字符数组是一个固定大小的数据结构,在定义时会分配一段连续的内存空间。无论这些位置是否被实际使用,都会占据相应的内存区域。例如: ```c char array[30]; ``` 此语句会在栈上分配 30 个字节的空间给 `array` 变量[^1]。 即使只向这个数组中存储少量数据(比如仅存入 `"abc"`),剩余未使用的部分仍然会被保留并可能填充为默认值(通常是 `\0` 或其他初始化值)。因此,字符数组的实际内存消耗由其声明长度决定,而不是所保存的内容长度。 #### 2. 字符串的内存占用 在 C 和 C++ 中,“字符串”通常是指以空终止符 (`\0`) 结束的一系列字符集合。虽然表面上看它也是通过字符数组实现的,但是它的逻辑概念更强调内容的有效范围——即从起始地址到第一个遇到的 '\0' 前的所有字符构成完整的字符串实体[^2]。 对于标准库支持下的动态管理型对象如 std::string (C++) 来讲,则涉及更多额外开销用于追踪内部状态信息,像当前容量(capacity),真实尺寸(size)以及指向缓冲区首址的指针等等[^3]。这意味着即便两个同样显示长度的文字序列也可能因为各自配置的不同而有不同的整体资源需求情况存在。 具体而言: - 如果我们创建了一个简单的静态字符串常量 `"hello world!"`, 那么除了这十一个可见ASCII单位外加结束标记共十二单元之外不会再有别的附加成分; - 而当运用 STL 的时候, 如下所示实例化过程将会引入更多的间接成本: ```cpp std::string str = "example"; ``` 这里不仅包含了原始文本本身所需的储存面积,还包括了用来维护容器特性的元数据领域,从而使得总体积增大了一些比例[^3]。 #### 3. 总结对比 | 特性 | 字符数组 | 字符串 | |--------------------|---------------------------------------|---------------------------------------| | **内存分配方式** | 编译期预设固定数量 | 动态调整 | | **最小内存占用** | 至少等于定义长度 | 实际所需加上一些控制字段 | | **灵活性** | 不具备自动扩展能力 | 支持按需增长 | 综上所述,尽管两者都基于相似的基础构建模块运作机制有所重叠之处;但从管理和操作便利角度出发考虑的话,现代高级抽象封装形式往往能够提供更好的用户体验效果的同时也伴随着不可避免的一些效率折衷考量因素在里面[^1][^2]. ```cpp // 示例代码展示两者的不同 #include <iostream> #include <cstring> int main() { char fixedArray[50]; // 明确指定最大可容纳49个有效字符+1个'\0' strcpy(fixedArray, "short text"); std::string dynamicString = "longer textual content that may grow over time"; std::cout << "Fixed Array Size: " << sizeof(fixedArray) << " bytes\n"; std::cout << "Dynamic String Capacity: " << dynamicString.capacity() << " characters\n"; return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值