串:
什么是串?把若干单独个体连接在一起就是一个串。在数据结构中,我们使用的无论是顺序表或者是链表,都是讲个体链接在一起的方法,所以我们利用前面学习的知识,将个体连接在一起实现串的模式匹配(字串在主串中查找的过程),后面将介绍一种简单的子串查找算法BF算法(Brute-Force算法)和KMP算法。
1. 串的概念 字符串简称串,是一种特殊的线性表,它的数据元素仅由一个字符组成。 2. 串的定义 串(String)是由零个或多个字符组成的有限序列,又称字符串。
package com.usts.edu.string;
/**
* Created by Guanzhong Hu
* Date :2019/12/28
* Description : 串的接口
* Version :1.0
*/
public interface IString {
public void clear();//将一个已经存在的串置空
public boolean isEmpty();// 根据串长进行判断,如果为0则为空,上述clear()则是将串置空方法 curlen = 0;
public int length(); // 根据curlen判断串长
public char charAt(int index); // 根据指针获取某位置的元素 区间[0,length()-1]
public IString substring(int begin,int end); // 根据头尾指针切割串,begin & end 区间 [0,length-1].[1,length()]
public IString insert(int offset,IString str); // 从某个字符插入串,offset区间[0,length()] 因为可以尾巴插入
public IString delete(int begin,int end); // 从[begin,end] 区间删除串,begin & end 区间 [0,length-1].[1,length()]
public IString concat(IString str); //把str链接在当前串后
public int compareTo(IString str); // 当前串和目标串进行比较,当前串 > 目标串 则返回 1,= 返回 0, < 返回-1;
public int indexOf(IString str,int begin); //从begin搜索非空串str,目标存在则返回index,不存在则返回-1
}
package com.usts.edu.string;
/**
* Created by Guanzhong Hu
* Date :2019/12/28
* Description : 串的顺序存储结构
* Version :1.0
*/
//TODO
public class SeqString implements IString {
/**
* 1、串的概念 字符串简称串,是一种特殊的线性表,它的数据元素仅由一个字符组成。
* 2、串的定义 串(String)是由零个或多个字符组成的有限序列,又称字符串。
*/
private char[] strvalue; //字符数组,存放串值
private int curlen; //当前串的长度
//构造方法1,构造一个空串
public SeqString() {
strvalue = new char[0];
curlen = 0;
}
//构造方法2,以字符串常量构造串对象
public SeqString(String str) {
if (str != null) {
char[] tempchararray = str.toCharArray();
strvalue = tempchararray;
curlen = tempchararray.length;
}
}
//构造方法3,以字符数组构造串对象
public SeqString(char[] value) {
this.strvalue = new char[value.length];
for (int i = 0; i < value.length; i++) { //复制数组
this.strvalue[i] = value[i];
}
curlen = value.length;
}
//将一个已经存在的串置成空串
public void clear() {
this.curlen = 0;
}
//判断当前串是否为空,为空则返回true,否则返回false
public boolean isEmpty() {
return curlen == 0;
}
//返回字符串长度
public int length() {
return curlen; //区别: strvalue.length是数组容量
}
//返回字符串中序号为index的字符
public char charAt(int index) {
if ((index < 0) || (index >= curlen)) {
throw new StringIndexOutOfBoundsException(index);
}
return strvalue[index];
}
//将字符串中序号为index的字符设置为ch
public void setCharAt(int index, char ch) {
if ((index < 0) || (index >= curlen)) {
throw new StringIndexOutOfBoundsException(index);
}
strvalue[index] = ch;
}
public void allocate(int newCapacity) //扩充容量,参数指定最小容量
{
char[] temp = strvalue; //复制数组
strvalue = new char[newCapacity];
for (int i = 0; i < temp.length; i++) {
strvalue[i] = temp[i];
}
}
//返回串中序号从begin至end-1的子串
public IString substring(int begin, int end) {
if (begin < 0) {
throw new StringIndexOutOfBoundsException("起始位置不能小于0");
}
if (end > curlen) {
throw new StringIndexOutOfBoundsException("结束位置不能大于串的当前长度:" + curlen);
}
if (begin > end) {
throw new StringIndexOutOfBoundsException("开始位置不能大于结束位置");
}
if (begin == 0 && end == curlen) {
return this;
} else {
char[] buffer = new char[end - begin];
for (int i = 0; i < buffer.length; i++) //复制子串
{
buffer[i] = this.strvalue[i + begin];
}
return new SeqString(buffer);
}
}
//返回串中序号从begin至串尾的子串
public IString substring(int begin) {
return substring(begin, strvalue.length);
}
//在当前串的第offset个字符之前插入串str,0<=offset<=curlen
public IString insert(int offset, IString str) {
if ((offset < 0) || (offset > this.curlen)) {
throw new StringIndexOutOfBoundsException("插入位置不合法");
}
int len = str.length();
int newCount = this.curlen + len;
if (newCount > strvalue.length) {
allocate(newCount); // 插入空间不足,需扩充容量
}
for (int i = this.curlen - 1; i >= offset; i--) {
strvalue[len + i] = strvalue[i]; //从offset开始向后移动len个字符
}
for (int i = 0; i < len; i++) //复制字符串str
{
strvalue[offset + i] = str.charAt(i);
}
this.curlen = newCount;
return this;
}
//删除从begin到end-1的子串, 0≤begin≤length()-1,1≤end≤length()。
public IString delete(int begin, int end) {
if (begin < 0) {
throw new StringIndexOutOfBoundsException("起始位置不能小于0");
}
if (end > curlen) {
throw new StringIndexOutOfBoundsException("结束位置不能大于串的当前长度:" + curlen);
}
if (begin > end) {
throw new StringIndexOutOfBoundsException("开始位置不能大于结束位置");
}
for (int i = 0; i < curlen - end; i++) //从end开始至串尾的子串向前移动到从begin开始的位置
{
strvalue[begin + i] = strvalue[end + i];
}
curlen = curlen - (end - begin); //当前串长度减去end-begin
return this;
}
//添加指定串str到当前串尾
public IString concat(IString str) {
return insert(curlen, str);
}
//将字符c连接到到当前串尾
public IString concat(char c) {
int newCount = curlen + 1;
if (newCount > strvalue.length) {
allocate(newCount);
}
strvalue[curlen++] = c;
return this;
}
//比较串
public int compareTo(IString str) {
return compareTo((SeqString) str);
}
public int compareTo(SeqString str) { //比较串
//若当前对象的串值大于str的串值,则函数返回一个正整数
//若当前对象的串值等于str的串值,则函数返回0
//若当前对象的串值小于str的串值,则函数返回一个负整数
int len1 = curlen;
int len2 = str.curlen;
int n = Math.min(len1, len2);
for (int k = 0; k < n; k++) {
if (strvalue[k] != str.strvalue[k]) {
return (strvalue[k] - str.strvalue[k]);
}
}
return len1 - len2; //返回两个字符串长度的数值差
}
public String toString() {
return new String(strvalue, 0, curlen); //以字符数组strvalue构造串
}
//计算模式串T的next[]函数值
protected int[] getNext(IString T) {
int[] next = new int[T.length()]; //next[]数组
int j = 1; //主串指针
int k = 0; //模式串指针
next[0] = -1;
if (T.length() > 1) {
next[1] = 0;
}
while (j < T.length() - 1) {
if (T.charAt(j) == T.charAt(k)) { //匹配
next[j + 1] = k + 1;
j++;
k++;
} else if (k == 0) { //失配
next[j + 1] = 0;
j++;
} else {
k = next[k];
}
}
return (next);
}
//计算模式串T的nextval[]函数值
protected int[] getNextVal(IString T) {
int[] nextval = new int[T.length()]; //nextval[]数组
int j = 0;
int k = -1;
nextval[0] = -1;
while (j < T.length() - 1) {
if (k == -1 || T.charAt(j) == T.charAt(k)) {
j++;
k++;
if (T.charAt(j) != T.charAt(k)) {
nextval[j] = k;
} else {
nextval[j] = nextval[k];
}
} else {
k = nextval[k];
}
}
return (nextval);
}
}
gitee源码地址: