【KMP+随机算法(Monta Carlo+Las Vegas)】字符串匹配 思路解析和代码

字符串匹配

对于字符串X和模式串Y(由0-1组成),使用两类随机算法,蒙特卡洛和拉斯维加斯算法求解两串是否匹配,随后再使用KMP检验两串是否匹配进行验证,统计三种算法的运行时间和蒙特卡洛算法的错误率,分别对字符串X长度为50,500,5000,50000进行检验,模式串Y不能太短

个人思路

思路

KMP算法
  • next[j]表示模式串的子串0 ~ j与 子串 j+1 ~ 模式串.size() 的最长相等前后缀 的前缀的最后一位
  • 使用根据模式串,计算各位其对应的next[]数组
  • 执行KMP算法,遍历字符串X,i指向字符串的欲比较位,j指向模式串匹配的最后一位,若X[i] == Y[j + 1],模式串的指针j后移;若X[i] != Y[j + 1],则 j = next[j]
随机算法

通过对字符串“取指纹”判断字符串是否相等
取指纹的方法:

  1. 由于字符串和模式串是由0-1组成,将字符串和模式串由二进制转换为十进制
  2. 随机生成一个小于M的整数P (P为素数),M的大小可以自己定义
  3. 对字符串的十进制编码与P做取模运算
  4. 若字符串和模式串的取模结果相同,则视为二者匹配
Monta Carlo算法
  • 对字符串和模式串取指纹
  • 取指纹后的结果相等则说明两字符串匹配,不等说明不匹配
Las Vegas算法
  • 在蒙特卡洛算法的基础上进行优化
  • 当两字符串的取指纹结果相等时,则进行逐一比对,若比对结果不同,则继续向后进行模式匹配
Monta Carlo算法和Las Vegas算法
  • 蒙特卡洛算法得到的解可能是正确的也可能是错误的,当数量级足够大时,算法出错的概率可以忽略
  • 拉斯维加斯算法得到的解一定是正确的解,但存在无解的情况

结论

  • 从运行的结果来看,蒙特卡洛算法的错误率与模式串Y长度无关(迭代次数过少,可以尝试一下10000次迭代,与X长度的关系不明显)
  • X的长度越大,蒙特卡洛算法错误率越高,这是否与算法实现和取指纹方法有关-----原因是随机数P的取值问题,随机数P应当取一个较大的素数
  • 当P一定大时,蒙特卡洛算法的出错率要比1/n小得多

为什么取模要取质数

  • 对素数取模一般能得到较好的离散结果,素数取模可以尽可能地避免模数相同之间的公因数,来达到减少冲突的目的;如果取合数,不同数字取模后的会出现结果相同的情况(发生冲突),也就是离散效果都不好

个人思路代码

循环执行
/*
 单次执行KMP,MontaCarlo,LasVegas
 * @Author: LLX 
 * @Date: 2020-11-03 13:30:58 
 * @Last Modified by: SEUer
 * @Last Modified time: 2020-11-03 16:12:08
 */
#include<bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7;
typedef long long ll;
string x;//原字符串
string y;//模式串
//作用:当j+1位匹配失败时,j应该回退到的位置
vector<int> yNext;//KMP next数组,标志模式串中最长相等前后缀 的前缀最后一位的下标
int xSize, ySize;
void init(int xSize, int ySize){
   
    x = "";//初始化清空
    for(int i = 0; i < xSize; ++i){
   
        int num = (int)(round(1.0 * rand() / RAND_MAX));
        x += '0' + num;
    }
    y = "";
    for(int i = 0; i < ySize; ++i){
   
        int num = (int)(round(1.0 * rand() / RAND_MAX));
        y += '0' + num;
    }
    printf("\n");
}
void getNext(){
   
    int j = 
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值