字符串的操作(基本函数&KMP&字符串哈希)

目录

1.基本字符函数

2.KMP算法

3.字符串哈希


1.基本字符函数

    1.字符串中常用函数  

 (1): 查找函数find();str.find(“ab”,2)的意思是查找str中str[2]到str[n-1]范围的位置;str.rfind(“ab”,2)的意思是找到str[0]到str[2]之间ab的位置。

   (2): 截取函数substr();如:str.substr(3)是截取str[3]之后的字符;str.substr(2,4)是截取从str[2]开始的4个字符组成的字符串(包括str[2])

   (3): 替换函数replace();如:str.replace(2,4,”lk”),返回把str[2]到str[2+(4-1)]的内容替换为“lk”的结果;str.replace(2,4,”abcd”,3),返回把str[2]到str[2+(4-1)]的内容替换为abcd的前三个字符的结果。

   (4): 插入函数insert();如:str.insert(2,”kjh”),从str[2]位置开始添加字符串“kjh”.

   (5):追加字符:push_back()和append()函数;如:在字符串的尾部添加字符串avs,str.append(“avs’),   str.push_back(“avs”);

  (6): 交换函数swap();如:str1.swap(str2),将字符串str1和str2交换。

  (7): 字符串比较:compare();如:str1.compare(str2);

  (8): strcat()函数,将两个字符串连接。

    2.还有一些其他的函数,具体看如下链接:https://blog.csdn.net/error0_dameng/article/details/81535374

https://blog.csdn.net/Hanxuwei/article/details/110366590


2.KMP算法

注意:KMP算法的本质其实就是找匹配子串最大公共前后缀。但是,要知道它的公共前后缀要小于查找字串的长度。

https://www.bilibili.com/video/BV1jb411V78H?from=search&seid=13292532469986190159

https://blog.csdn.net/ZQH_Horizon/article/details/7343269

	int i=0,j=-1;
	p[0]=-1;
	while(s[i]){
		if(j==-1||s[i]==s[j]){
			i++;j++;
			p[i]=j;
		}
		else j=p[j];
	}

如上述求next[]值的过程,可以直接看成求该位置字符之前字符串的前缀和后缀有多少相同字符(最大公共前后缀)。如图所示:ABA就是最长公共前后缀。

起初我不太了解为什么

(1)next[0]=-1,后来我想到一个形象的表达方法。因为如果字符串的第一个字符不匹配的话那么,这个第一位字符就必须往后移动一位,那么母串的首位字符就要和第一位字符位置之前的字符比较,因为第一位字符下标为0,那么它前面的字符下标就是-1。 但是,当博主看一些大佬的讲解里面都说模式串第一个字符的next[ ] 可以将其规定为任意一个唯一的标志数,注意是唯一的,即不会与后续字符的next [ ] 值相同,next[0]的值只是为我们提供一个参考,让我们知道什么时候,模式串已经到达了第一个字符。所以只要和后面next[]里面的数不相同都可以,如定义为-1,-5,-8都可。

(2)其次,又因为子串第二位字符的前后缀都只有第一位字符自己,那么它的最长公共前后缀就是1,如果该位置字符不匹配,那么就向后移动1位。此时,母串该位置字符需要和子串移动后的该位置字符比较,由上可以得出子串移动后该位置字符的下标位0(也就是子串第一个字符)。所以next[1]=0。

(3) 它的意思是让最长公共前缀移动到最长公共后缀的位置上。

else j=p[j];

而这一步骤就是求子串的最长公共前后缀 。

if(j==-1||s[i]==s[j]){
			i++;j++;
			p[i]=j;
		}

3.字符串哈希

所谓字符串哈希就是构造一个数字使之唯一代表一个字符串有,

如abcd,我们取各个字母的ASCII码值减去a的ASCII码值+1,便得到abcd分别对应数字1,2,3,4,接下来再取一个进制如23进行组合即可。保险起见,进制要大于每一个字符对应的数字(负数情况另外讨论)。否则会出现如下情况:

a b c d  e 分别对应 1 2 3 4  25,若此时取23进制,那么b和e的哈希值相同,会被判断为是同一字符串。

个人认为该类型题主要是记住哈希公式就可以了。

哈希公式:t=t*B+(ULL)(s[i]-'a'-1);

一般来讲这种类型的题只是需要找有多少个不同的字符串,如下:

给定 N 个字符串(第 i 个字符串长度为 Mi,字符串内包含数字、大小写字母,大小写敏感),请求出 N个字符串中共有多少个不同的字符串。

输入:

5

As

As

Fdskj

Sdff42

Fd

输出:

4

#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ULL;    //哈希值可能非常大
const int N=1e4+5;
const ULL B=29;    //进制
ULL hashT[N];      //用于储存每一个字符串的哈希值
char input[N];
int n,tmp;
int ans;
ULL hashf(char s[])    //生成字符串哈希值
{
    tmp=0;
    for(int i=0;i<strlen(s);i++)    //像处理字符数字的过程,也可以从右到左写
        tmp=tmp*B+(ULL)(s[i]-'a'+1);//后者强转换成ULL进制
    return tmp;
}
 

int main()
{
    cin>>n;
    for(int i=0;i<n;i++)
    {
        scanf("%s",input);
        hashT[i]=hashf(input);
    }
    sort(hashT,hashT+n);
    ans=1;
    for(int i=1;i<n;i++)
    {
        if(hashT[i]!=hashT[i-1]) ans++;    //排序完哈希值不同就说明是不同的字符串
    }
    printf("%d\n",ans);
return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值