串存储结构
字符串要单独用一种存储结构来存储,称为串存储结构,串指的就是字符串。
串有三种存储方式
定长顺序存储结构(静态)
char str[100]="hello world";
堆分配存储结构(动态数组存储字符串)
void test1()
{
char* str1 = (char*)malloc(10 * sizeof(char)); //申请10个char大小的动态数组
char* str2 = (char*)malloc(10 * sizeof(char));
strcpy_s(str1, strlen(str1)+1,"hello");
strcpy_s(str2, strlen(str2)+1,"world");
int len1 = strlen(str1);
int len2 = strlen(str2);
if (len1 < len1 + len2)
{
str1 = (char*)realloc(str1, (len1+len2+1) * sizeof(char)); //如果不够可以进行申请空间 之前为10,现在扩大为len1+len2+1
}
for (int i = len1; i < len1 + len2; i++)
{
str1[i] = str2[i - len1];
}
str1[len1 + len2] = '\0';
cout << str1 << endl;
}
链式存储结构
#define char_max_size 3
typedef struct linkchar
{
char a[char_max_size];
struct linkchar* next;
};
void printlinkchar(linkchar* c)
{
linkchar* temp = c;
while (temp->next != NULL)
{
for (int i = 0; i < char_max_size; i++)
{
cout << temp->a[i];
}
temp = temp->next;
}
}
linkchar* initlinkchar(const char* a)
{
linkchar* head = (linkchar*)malloc(sizeof(linkchar));
head->next = NULL;
linkchar* temp = head;
int len = strlen(a);
int num = len / char_max_size + 1;
for (int i = 0; i < num; i++)
{
linkchar* b = (linkchar*)malloc(sizeof(linkchar));
temp->next = b;
b->next = NULL;
for (int j = 0; j < char_max_size; j++)
{
if (char_max_size * i + j < len)
{
temp->a[j] = a[char_max_size * i + j];
}
else
{
temp->a[j] = ' ';
}
}
temp = b;
}
return head;
}
串模式匹配算法
BF算法
void BFpp(char* a, char* b)
{
char* i = a;
char* j = b;
int lena = strlen(a);
int lenb = strlen(b);
int size = 0;
int time = 0;
while (strlen(a)>=strlen(b) && strlen(j)!=0)
{
if (*i == *j)
{
i++;
j++;
size++;
time++;
}
else
{
j = b;
a++;
i = a;
size = 0;
//break;
}
}
if (size == lenb)
{
cout << "pp " <<time<< endl;
}
if (size != lenb)
{
cout << "bcz" << endl;
}
}
KMP算法
void getnext(char* b,int* next)
{
int i = 0;
int k = -1;
next[i] = k;
while (i < strlen(b))
{
if (k == -1 || b[i] == b[k])
{
i++;
k++;
next[i] = k;
}
else
{
k = next[k];
}
}
}
void KMPpp(char* a, char* b)
{
char* i = a;
char* j = b;
int lena = strlen(a);
int lenb = strlen(b);
int size = 0;
char first = *a;
//int next[6] = {-1,0,0,1,0}; //abada
int next[255];
getnext(b,next);
int time = 0;
while (size != lenb)
{
if (next[size]==-1 || *i == *j)
{
i++;
j++;
size++;
}
else
{
int x = next[size];
j = b + x;
size = x;
}
if (size == lenb)
{
cout << "pp " <<time<< endl;
break;
}
time++;
if ( strlen(i) < strlen(j) )
{
cout << "bcz" << endl;
break;
}
}
}
获取子串next数组的代码有点难以理解,我是通过下面这两个链接才搞明白的
KMP模式匹配(中)如何理解反人类next数组代码!_哔哩哔哩_bilibili
KMP模式匹配算法中next和nextval数组的快速求解_czw8528的专栏-CSDN博客_next和nextval
KMP算法优化
getnextval
void getnextval(char* b, int* nextval)
{
int i = 0;
int k = -1;
nextval[i] = k;
while (i < strlen(b))
{
if (k == -1 || b[i] == b[k])
{
i++;
k++;
if (b[k] != b[i])
{
nextval[i] = k;
}
else
{
nextval[i] = nextval[k];
}
}
else
{
k = nextval[k];
}
}
}
应用: 字符过滤系统
void initdl(dl5& d)
{
d.end = new char[max_sized];
d.top = d.end;
d.size = max_sized;
}
void insertdl(dl5& d,char val)
{
if (d.top - d.end == d.size)
{
cout << "full" << endl;
exit;
}
*d.top = val;
d.top++;
}
char pushdl(dl5& d)
{
char e = *d.end;
d.end++;
return e;
}
void getnextval1(char* g, int* nextval)
{
int k = -1;
int i = 0;
nextval[i] = k;
while (i < strlen(g))
{
if (k == -1 || g[i] == g[k])
{
i++;
k++;
if (g[i] != g[k])
{
nextval[i] = k;
}
else
{
nextval[i] = nextval[k];
}
}
else
{
k = nextval[k];
}
}
}
void gl(char* a,char* g)
{
int i = 0, j = 0;
int lena = strlen(a);
int leng = strlen(g);
int nextval[20];
getnextval1(g, nextval);
int x[20];
int y = 0;
while (i < lena)
{
if (j == -1 || a[i] == g[j])
{
i++;
j++;
}
else
{
j = nextval[j];
}
if (j == leng)
{
x[y] = i - leng;
y++;
}
}
for (int i = 0; i < y; i++)
{
cout << x[i] << " ";
}
cout << "输入代替的字母:";
char str1[20];
cin >> str1;
dl5 d;
initdl(d);
for (int i = 0; i < y; i++)
{
int t = x[i] + (strlen(str1)- leng) * i ;
for (int j = t + 1; j < strlen(a); j++)
{
insertdl(d, a[j]);
}
for (int k = 0; k < strlen(str1); k++)
{
a[t + k] = str1[k];
}
int lend = d.top - d.end;
for (int p = 0; p < lend; p++)
{
char x2 = pushdl(d);
a[t + strlen(str1) + p] = x2;
}
}
}