0
点赞
收藏
分享

微信扫一扫

字符串(string)总结(包括用法+算法)

探头的新芽 2022-04-30 阅读 60
c++

时隔多年,我又来写总结啦!!!

字符串string用法+算法总结

先总述一下
字符串(string)是一种常用的数据结构,存储方式类似于数组,c++里规定其存储的起始下标为0,通常用 l e n = s . s i z e ( ) len=s.size() len=s.size()来表示字符串长度。

另外,字符串也可以char数组的方式实现。此时需用len=strlen(s)求其长度

用法

c++中,string自带的用法有很多,此处仅介绍几个较为初级的、常用的用法。
(注:char数组没有以下用法)

插入

string支持最基础的+=插入。

string s="abcd";
char ch='e';
s+=ch;
//此时s="abcde"

下面列举 i n s e r t ( ) insert() insert()函数的具体用法

string s="abcd",ch="wxyz";
s.insert(2,ch);//在字符串s的位置2上插入字符串ch,此时s="abwxyzcd"
s.inzert(2,ch,1,3);//在字符串s的2的位置上插入字符串ch中以位置1为开头,长度为3的字符串,此时s="abxyzcd"
char ch1='x';
s.insert(2,3,ch1);//在字符串s的位置2上插入3个字符ch1,此时s="abxxxcd"

删除

string s="abcdefg";
s.erase(2,4);//删除字符串s的以位置2为开头、长度为4的子串,此时s="abg"

替换

string s="abcdefg",ch="xyz";
s.replace(2,4,ch);//将字符串s的以位置2为开头,长度为4的子串换成字符串ch,此时s="abxyzg"

用法到此结束。

算法

引入hash

hash表,又称散列表,一般由hash函数和链表结构共同实现。

hash算法的本质是建立映射关系,其他类似的算法还有离散化和 m a p ( 数 据 结 构 ) map(数据结构) map。hash的思想是取一个 p p p值,将数字 x x x存在 h e a d head head数组中 x m o d    p x\mod p xmodp的格子里。但是这显然会有冲突(既必定存在多个 x x x,使得 x m o d    p x\mod p xmodp的值相等)。处理这种冲突的最常用方法为拉链法——开一个链表结构(类似于图论中的链式前向星)。具体写法见code:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int a[maxn],head[maxn]/*存储的格子*/;
int A/*数组长度*/,p/*为了达到效果,p要选大于A的质数*/,tot=0;
struct star {//链式前向星
	int nxt,val;
};
star h[maxn];
bool check(int x) {//找质数
	if(x==1) return 0;
	if(x==2) return 1;
	if(x%2==0) return 0;
	for(int j=3;j<=sqrt(x);j+=2)
		if(x%j==0) return 0;
	return 1;
}
void add(int x) {
	int k=(x%p+p)%p;//数字x的hash值,这么写是为了避免x<0的情况
	h[++tot].val=x;//数字原来的值
	h[tot].nxt=head[k];//数字在格子里的位置
	head[k]=tot;//这个格子最后一次存入数字是在第tot个前向星中
}
bool Find(int x) {//查找数字x是否出现过
	for(int j=head[x%p];j!=-1;j=h[j].nxt)
		if(h[j].val==x) return 1;//出现过
	return 0;
}
int main() {
	scanf("%d",&A);
	for(int i=1;i<=A;i++)
		scanf("%d",&a[i]);
	memset(head,-1,sizeof(head));
	for(p=A+1;;p++)
		if(check(p)) break;
	for(int i=1;i<=A;i++)
		add(a[i]);//插入
	return 0;
}

hash算法优于离散化和map的地方在于它的时间复杂度是严格O(n)的。在忽略常数的情况下

字符串hash

普通的hash算法针对的是数字,无法存储字符串。这个算法就是针对字符串而出现的。
对于一个字符串 s s s,它的hash值求法是:将 s s s中的每个字符都转换成一个数字,然后选取一个数 b a s e base base进制数,将 s s s转换位一个 b a s e base base进制数的数字。为了方便,我们一般将字符对应的ASCLL码作为其转换的数字,进制数一般取131(因为小写字母z的ASCLL码是所有大小写字母中最大的,为126)。因为这个数字过大,所以我们要进行取模运算。又因为取模运算常数很大,所以我们引入一个unsigned long long(无符号64位整型,范围0~264-1)。当数字大于 0 ∼ 0 \sim 0 264 − 1 -1 1时,它会自动对264取模,而且常数很小(可以想象成位运算)。
所以,一般查找这个字符串有没有出现过时,仅靠字符串hash是不够的,需要搭配数字hash共同实现。code如下:

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int maxn=50050;
int mod=50021;
struct Hash {//数字hash(见上文)
	int nxt;
	ull val;
};
Hash edge[maxn];
int p=131,n;
int head[maxn],tot=0;
ull Get(string s) {//字符串hash值
	ull num=0;
	for(int j=0;j<s.size();j++)
		num=num*p+(ull)(s[j]-'a'+1);
	return num;
}
int H(ull x) {
	return (x%mod+mod)%mod;
}
bool add(ull x) {
	int k=H(x);
	for(int j=head[k];j!=-1;j=edge[j].nxt)
		if(edge[j].val==x) return 1;//出现过
	edge[++tot].val=x;//未出现,插入
	edge[tot].nxt=head[k];
	head[k]=tot;
	return 0;
}
int main() {
	scanf("%d",&n);
	memset(head,-1,sizeof(head));
	for(int i=1;i<=n;i++) {
		string x;
		cin>>x;
		ull res=Get(x);//得出字符串x的hash值
		if(add(res)/*查找res这个数字有没有出现过,如果没有就插入*/) 
			printf("%d\n",i);
	}
	return 0;
}

现在最基础的字符串hash我们已经了解。通过字符串hash我们还可完成更多操作。我们先引入几个公式:

H(S):字符串S的hash值
H(S+T)=H(S)*p^length(T)+H(T)
H(T)=H(S+T)-H(S)*p^length(T)

通过这三个公式,我们即可在O(n)的时间复杂度内求出字符串S的hash值,并在O(1)的时间复杂度内求出S的任意子串的hash值。例题:兔子与兔子
code:

#include<bits/stdc++.h>
using namespace std;
string s;
const int maxn=1e6+10;
typedef unsigned long long ull;
ull f[maxn],q[maxn];
int p=131;
void Prepare() {
	for(int i=0;i<s.size();i++) {
		if(i==0) f[i+1]=(ull)(s[i]-'a'+1);
		else f[i+1]=f[i]*p+(ull)(s[i]-'a'+1);
		if(i==0) q[i]=1;
		else q[i]=q[i-1]*p;
	}
}
int main() {
	cin>>s;
	Prepare();//O(n)求s各个位置的hash值
	int m;
	scanf("%d",&m);
	for(int i=1;i<=m;i++) {
		int l1,l2,r1,r2;
		scanf("%d%d%d%d",&l1,&l2,&r1,&r2);
		//判断区间[l1,l2]与[r1,r2]是否相等
		ull h1=f[l2]-f[l1-1]*q[l2-l1+1];
		ull h2=f[r2]-f[r1-1]*q[r2-r1+1];
		if(h1==h2) puts("Yes");
		else puts("No");
	}
	return 0;
}

KMP模式匹配

待更

最小表示法

待更

举报

相关推荐

0 条评论