#define _CRT_SEURE_NO_WARNINGS
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 100
using namespace std;
typedef struct st
{
char* ch;
int length;
int strSize;
}String;
String creatNullString()
{
String str;
str.length = 0;
str.strSize = MAXSIZE;
str.ch = (char*)malloc(MAXSIZE*sizeof(char));
return str;
}
bool isEmpty(String str)
{
if (str.length == 0)
{
return true;
}
else
{
return false;
}
}
void strAssign(String* str,const char str2[])//串赋值
{
int i = 0;
while (str2[i] != '\0')//str2长度
{
i++;
}
if (str->length < i)
{
char* temp = str->ch;
str->ch = (char*)realloc(str->ch,i * sizeof(char));
str->strSize = i;
free(temp);
}
str->length = i;
for (i = 0; i < str->length; i++)
{
str->ch[i] = str2[i];
}
}
void strCopy(String* str1, String str2)
{
if (str1->strSize < str2.strSize)
{
char*temp = str1->ch;
str1->ch = (char*)realloc(str1->ch, str2.strSize);
str1->strSize = str2.strSize;
free(temp);
}
str1->length = str2.length;
for (int i = 0; i < str1->length; i++)
{
str1->ch[i] = str2.ch[i];
}
}
void strConcat(String* str, String str1, String str2)
{
int i;
if (str->strSize < str1.length + str2.length)
{
char* temp = str->ch;
str->ch = (char*)realloc(str->ch,(str1.length + str2.length) * sizeof(char));
str->strSize = str1.length + str2.length;
free(temp);
}
str->length = str1.length + str2.length;
for (i = 0; i < str1.length; i++)
{
str->ch[i] = str1.ch[i];
}
for (i = str1.length; i < str->length; i++)
{
str->ch[i] = str2.ch[i];
}
}
int subString(String s, int begin, int len, String* t)//取子串
{
if (begin <= 0 || len<0 || len>s.length || len > s.length - begin)
{
printf("参数有误!");
return 0;
}
t->length = len;
for (int i = 0; i < t->length; i++)
{
t->ch[i] = s.ch[begin - 1 + i];
}
return 1;
}
int insertString(String* str, int begin, String str1)//把str1插到str第begin个之后
{
int i;
if (begin <= 0 || begin > str->length)
{
printf("参数有误!");
return 0;
}
if (str->strSize < str->length + str1.length)
{
char* temp= str->ch;
str->ch = (char*)realloc(str->ch, (str->length + str1.length) * sizeof(char));
str->strSize = str->length + str1.length;
free(temp);
}
for (i = str->length - 1; i >= begin; i--)
{
str->ch[i + str1.length] = str->ch[i];
}
str->length = str->length + str1.length;
for (i = 0; i <= str1.length; i++)
{
str->ch[begin + i] = str1.ch[i];
}
}
int indexOf(String s, String t, int index)//从下标为index开始找
{
if (isEmpty(t) || t.length > s.length || index <= 0 || index > s.length)
{
printf("参数有误");
return -1;
}
int i = index;
int j = 1;
while (i<=s.length && j<=t.length)
{
if (s.ch[i-1] == t.ch[j-1])
{
i++;
j++;
}
else
{
i = i - j + 2;
j = 1;
}
if (j == t.length+1)
{
return i - j + 1;
}
}
return -1;
}
int indexOf1(String s, String t, int index)//从下标为index开始找
{
if (isEmpty(t) || t.length > s.length || index <= 0 || index > s.length)
{
printf("参数有误");
return -1;
}
int i = index;
int j = 1;
while (i <= s.length && j <= t.length)
{
if (s.ch[i-1] == t.ch[j-1])
{
i++;
j++;
}
else
{
i = i - j + 2;
j = 1;
}
}
//printf("%d", i);
//printf("%d", j);
if (j == t.length+1)
{
return i - j + 1;
}
else
{
return -1;
}
}
void print(const String str)
{
for (int i = 0; i < str.length; i++)
{
cout << str.ch[i];
}
}
void getNext(const String str,int next[])
{
int i = 1;//长
int j = 0;//模式串
next[1] = 0;
while (i < str.length)//next[1...str.length] 当i==str.length-1时进循环,i++后i==str.length,正好操作next[str.length].
{
if (j == 0 || str.ch[i-1] == str.ch[j-1])
{ //给next[i+1]赋值的时候,串的第i个元素也一定在比较的if条件里(给next[6]赋值时,比较的条件一定有a[4]),a[4]是第五个元素,进if后先加1变6,然后执行next[6]=j(正好是第六个元素的next值)
//给第i个元素赋next值得时候,它的前一个元素一定在比较的条件里
next[i + 1] = j + 1; //如果一样,就进if,给next[i]赋值
i++; //如果不一样且j!=0,那么i不动,j回撤。对于j:
j++; //1.最坏j退到0,然后进if,执行j++变1,然后给next[i],这说明:在第i个字符之前的字符没有任何重叠部分(abcda)a的next值(next[5]==1)
//2.j不一定退到0,他可以退到next[j],next[j]表示:子串的第j个元素和主串某个字符在比较的时候,如果不匹配,可以从子串的第next[j]个元素开始继续和主串的该字符进行匹配
//主串的失配字符往前,和子串的第next[j]个字符前(一直到开头)的串是一样的(就不用再比了)
//而j!=0且ch[i-1]!=ch[j-1],说明主串第i个字符和子串第j个字符失配了,这时i不动,ch[i-1]为第i个字符继续待比较;j=next[j](从第next[j]个位置开始比较)
//所以ch[j-1]正好是第j(next[j])个字符
}
else
{
j = next[j];//j除了一开始,再想要变0,只能进这个else
}
}
for (i = 1; i <= 20; i++)
printf("%d", next[i]);
}
//整个循环过程:next[1]==0 (j==next[1])
//第一次while结束后:next[2]==1,i==2,j==1(j==next[2]);(第一次while是固定的,得到的结果对于任何串都一样)
//第二次while开始:i==2,j==1 进if里比较(ch[1]==ch[0])也就是第一个字符和第二个字符比较
//1.相等:执行next[i+1]=j+1;也就是next[3]==2(给第三个元素赋next值时,比的是前两个元素,相等意味着这个串为aaxxx或者bbxxx)这个时候j==next[3]
//2.不等:(j==1不为0)进else把j变成0(j==next[1]),第三次while时一定进if,让next[3]==1
void getNext1(const String str, int next[])
{
int i = 1;
int j = 0;
next[1] = 0;
while (i < str.length)
{
if(j == 0 || str.ch[j - 1] == str.ch[i - 1])
{
j = j + 1;
i = i + 1;
if (str.ch[j - 1] != str.ch[i - 1])
{
next[i] = j;
}
else
{
next[i] = next[j];
}
}
else
{
j = next[j];
}
}
for (i = 1; i <= 20; i++)
printf("%d", next[i]);
}
int KMP(String str1, String str2)
{
int i = 1;
int j = 1;
int next[30];
getNext1(str2, next);
while (i <= str1.length && j<= str2.length)
{
if (j == 0||str2.ch[j - 1] == str1.ch[i - 1])
{
i++;
j++;
}
else
{
j = next[j];
}
}
if (j == str2.length + 1)
{
return i - str2.length;
}
else
{
return -1;
}
}
int main()
{
String s1 = creatNullString();
String s2 = creatNullString();
String s3 = creatNullString();
const char* p3 = "abaaaaa";
const char* p1 = "sbcd";
const char* p2 = "efgh";
//int next[28] = {100};
strAssign(&s1,p1);
strAssign(&s2,p2);
//getNext1(s1, next);
//int x = KMP(s1, s2);
//printf("%d", x);
//对于栈操作那个,是把一个pHead指针赋值给一个形参指针,形参指针只是pHead的一个副本,对形参的操作(开辟堆内存,赋值),在功能函数结束之后就被销毁了,pHead依然为空,不会改变。
//但这个不同,这是通过指针修改s1里的内容。把s1的地址给形参指针,通过指针修改s1里堆内存的内容,s1会改变。
strConcat(&s3, s1, s2);
print(s3);
}
(顺序存储)串的基本操作(包含BP,KMP)
最新推荐文章于 2022-04-16 22:35:16 发布