HDU2087 剪花布条 题解 KMP算法

醉酒当歌 提交于 2019-12-03 11:39:52

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2087
题目大意:给定字符串 \(s\)\(t\) ,找出 \(s\) 中出现不重叠的 \(t\) 的最多次数。
举个例子,\(s\) 串为 "abababa" , \(t\) 串为 "aba" ,虽然 \(s[0..2]、s[2..4]、s[4..6]\) 都为 "aba" ,但是如果都选出了的话,会有重叠部分,所以最多的方案是找到 \(s[0..2]、s[4..6]\) 这两个,是不重叠的。
题目分析:如果是要找 \(s\) 中所有的所有的 \(t\) 的话,每当找到的时候,会将 \(j\) 置为 \(nxt[j]\) ,那这里因为是需要不重叠,所以每当找到的时候,将 \(j\) 置为 \(-1\) ,就可以保证 \(s\) 中每个匹配子串的空间不重叠了。
实现代码如下:

#include <cstdio>
#include <string>
using namespace std;
const int maxn = 1001000;

int T, n, m, nxt[maxn], ans;
string s, t; // s代表母串,t代表子串
char ch[maxn];

string read() {
    scanf("%s", ch);
    string tmp_s = ch;
    return tmp_s;
}

void cal_next() {
    m = t.length();
    for (int i = 0, j = -1; i < m; i ++) {
        while (j != -1 && t[j+1] != t[i]) j = nxt[j];
        nxt[i] = (j+1 < i && t[j+1] == t[i]) ? ++j : -1;
    }
}

void find_s_has_distinct_t_count() {
    ans = 0, n = s.length(), cal_next();
    for (int i = 0, j = -1; i < n; i ++) {
        while (j != -1 && t[j+1] != s[i]) j = nxt[j];
        if (t[j+1] == s[i]) {
            j ++;
            if (j >= m-1) {
                ans ++;
                j = -1;
            }
        }
    }
    printf("%d\n", ans);
}

int main() {
    while (true) {
        s = read();
        if (s == "#") break;
        t = read();
        find_s_has_distinct_t_count();
    }
    return 0;
}

作者:zifeiy

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!