用彩票比喻字符串匹配_Sunday算法关键点解析

假设有种彩票,从每日00:00:00开始,一小时出来一个号(24小时出24个号 00:00:00~23:00:00,假设为 a~z);

彩民可以随意买5个号,只要在这一天出来的彩票序列中存在自己买的序列即中奖;

显然:

①最早的结果是在凌晨04:00:00出来的,此时,幸运的人都是一个样,不幸的人各有各的不幸;

②按照一种方式分,未中奖者可以分成:第1个号就没中 ;1中2没中;1,2中 3没中  这样5种情况的,这5种情况中又各自有各种不同的情况;

③未中奖者的希望都在未来,在未知的号;

④有些未中奖者,直到等到后一个号出来才可以确定是不是中奖,有些则在看到19(24-5=19)点的号的时候就已经确定不能中奖了;

当然,这样的彩票是有bug的,中奖概率与你的号有关。

 

说回Sunday算法,这个算法比经典的KMP算法年轻,1990年,相对也好理解。

想法就是,当前无论因何原因没中奖,即使只差那么一丁点,想要中奖,你也得依靠后面的号,为确保不遗漏,从之后的第一个新号就开始看,现在你把这个新的号纳入可能的范围,那么至少这个新号与你手中的某个号相同,否则无论你手中的号现在有百分之多少的相似度,纳入这个号之后,都必然无法完全匹配。

下面是代码,代码来源https://blog.csdn.net/q547550831/article/details/51860017

经作者允许粘贴至此,关键地方的注释做了补充

const int maxNum = 128;
int shift[maxNum];
int Sunday(const string& T, const string& P) {
    int n = T.length();
    int m = P.length();

    // 默认值,移动m+1位 //默认新出的号在你手中根本不存在
    for(int i = 0; i < maxNum; i++) {
        shift[i] = m + 1;
    }

    // 模式串P中每个字母出现的最后的下标
    // 所对应的主串参与匹配的最末位字符的下一位字符移动到该位,所需要的移动位数
    
    for(int i = 0; i < m; i++) {
        shift[P[i]] = m - i;//
    }

    // 模式串开始位置在主串的哪里
    int s = 0;
    // 模式串已经匹配到的位置
    int j;
    while(s <= n - m) {
        j = 0;
        while(T[s + j] == P[j]) {
            j++;
            // 匹配成功
            if(j >= m) {
                return s;
            }
        }
        // 找到主串中当前跟模式串匹配的最末字符的下一个字符
        // 在模式串中出现最后的位置
        // 所需要从(模式串末尾+1)移动到该位置的步数
        s += shift[T[s + m]];
    }
    return -1;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值