(1)串是内容受限的线性表,他限定了表中的元素为字符.
串的两种基本存储结构:顺序存储(常用)和链式存储。
主要有BF算法和KMP算法。
BF算法实现简单,但存在回溯,效率低,时间复杂度为O(m*n)。
KMP算法对BF算法进行改进,消除了回溯,提高了效率,世间复杂度为O(m+n)
(2)多维数组可以看成是线性表的推广,其特点是结构中的元素本身可以是具有某种结构的数据,但属于统一数据类型。数组一般采用顺序存储结构。
(3)广义表是另外一种线性表的推广形式,表中的元素可以使称为原子的单个元素,也可以是一个子表,所以线性表可以看成广义表的特例。广义表的结构相当灵活,在某种前提下,他可以兼容线性表,数组,树和有向图等各种常用的数据结构。广义表的常用操作有取表头和取表尾。广义表常采用链式存储结构:头尾链表的存储结构和扩展线性链表的存储结构。
1)BF算法
①size()和length()这两个函数是用来计算string类对象或者即STL对象方法。都是计算字符串长度。
②strlen()是函数,参数必须是字符型指针(char),计算从开始到结束(’\0‘),返回的长度大小不包括’\0’,也是计算字符长度。
③sizeof()是运算符,不能计算复杂内存分配空间大小。计算字符所占空间大小。*
#include<stdio.h>
#include<string>
#include<iostream>
using namespace std;
int Index_BF(string& s,string& t)
{
int i = 0, j = 0,count=0;
while (i < s.size()&&j<t.size())
{
if (s.at(i) == t.at(j))
{
i++;
j++;
count++;
}
else
{
i=i-j+1;
j = 0;
count = 0;
}
if (count ==t.size())
{
cout << "模式匹配成功,起始位置是:" << i - count + 1 << endl;
return (i - count + 1);
}
}
cout << "字符串匹配失败!"<<endl;
return 0;
}
int Index_BF(string s,string t,int pos)
{
int i = pos, j = 0;
while (i<=s.size()&&j<=t.size())
{
if (s[i] == t[j])
{
i++;
j++;
}
else
{
i = i - j + 1;
j = 0;
}
if (j > t.size())
{
cout << "模式匹配成功,起始位置是:" << i - t.size() << endl;
return (i - t.size() + 1);
}
}
cout << "字符串匹配失败!" << endl;
return 0;
}
int main(void)
{
string S;
string T;
cout << "请输入主串:";
cin >> S;
cout << endl;
cout << "请输入模板T:";
cin >> T;
cout << endl;
Index_BF(S,T,0);
system("pause");
return 0;
}
2)KMP算法
#pragma once
//str1为主串,str2为模式串,在str1中检查是否包含str2,存在则返回起始位置,不存在则返回-1
#include <iostream>
#include <string>
#include <vector>
using namespace std;
vector<int> getnext(const string &str2, vector<int> next)
{
next.clear();
next.resize(str2.size());
if (str2.length() == 1)
{
next[0] = -1;
return next;
}
next[0] = -1;
next[1] = 0;
int len = str2.length();
int i = 2, cn = 0;//cn为最长前缀的后一个字符
while (i < len)
{
if (str2[i - 1] == str2[cn]) //如果前一个字符和cn对应的值相等
next[i++] = ++cn;//如果相等则此处的值为,cn+1
else if (cn > 0)
cn = next[cn];//不等的话继续往前推
else
next[i++] = 0;//不等的话并未没法往前推就变为0
}
return next;
/*for (int i = 0; i < str2.size(); i++)
{
cout << next[i];
}*/
}
int kmp(const string &str1, const string &str2, vector<int> & next)
{
int i1 = 0, i2 = 0;
while (i1 < str1.length() && i2 < str2.length())
{
if (str1[i1] == str2[i2])//两者比对,相等则主串和模式串都加加
{
i1++;
i2++;
}
else if (next[i2] == -1)//两者没有匹配则进一步判断i2是否还有回退的资格,如果等于-1说明已经退到头了,则只能i1++;
{
i1++;
}
else//还可以退,则i2回到到next数组指定的位置再进行比对
i2 = next[i2];
}
return i2 == str2.length() ? i1 - i2 : -1;
//如果str2已经扫描完了说明已经找到了,返回str1中找到的起始位置;如果没有扫描完说明没有找到返回-1;
}
#include"kmp.h"
int main()
{
string str1, str2;
cout << "请输入主串:";
cin >> str1;
cout << "请输入模式:";
cin >> str2;
vector<int> next1(255);
vector<int> next2;
next2=getnext(str2,next1);
int k;
k = kmp(str1, str2, next2);
cout << "匹配成功,模式匹配的其实位置为:" << k;
system("pause");
return 0;
}