题目链接: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