字符串匹配
对于字符串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]
随机算法
通过对字符串“取指纹”判断字符串是否相等
取指纹的方法:
- 由于字符串和模式串是由0-1组成,将字符串和模式串由二进制转换为十进制
- 随机生成一个小于M的整数P (P为素数),M的大小可以自己定义
- 对字符串的十进制编码与P做取模运算
- 若字符串和模式串的取模结果相同,则视为二者匹配
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 =