KMP字符串匹配
String Matching
http://www.nowcoder.com/questionTerminal/00438b0bc9384ceeb65613346b42e88a
给定字符串T和P,求出P在T中出现的次数【KMP模板题】
https://blog.csdn.net/csyifanZhang/article/details/105728330
↑更好的阅读体验
这道题暴力很容易想到,不断的在T中找P的第一个元素,一旦找到了就看看是否T接下来的元素和P匹配,乍一看二分查找+比较好像,但是很容易退化,aaaaaaaaaa
匹配aaa
,还是很难受的
string s1, s2; while (cin>>s1>>s2) { ll res = 0, pos = 0, l = s2.size(); while ((pos = s1.find(s2[0])) >= 0 && s1.size() >= s2.size()) { if (s1.substr(pos, l) == s2)res++; s1 = s1.substr(pos + 1, s1.size() - 1); } cout << res << endl; }
所以这道题是一道KMP模板题,KMP详细教程,KMP的难点在于预处理next数组,而next数组威力无穷,AC自动机也使用了类似的算法。
ll nextt[MAX]; string s1, s2; void getNext(string s) { memset(nextt, 0, sizeof(nextt)); ll k = -1, i = 0; nextt[0] = -1; while (i < s.size()) { if (k == -1 || s[i] == s[k]) { if (s[++i] != s[++k])nextt[i] = k; else nextt[i] = nextt[k]; } else k = nextt[k]; } } ll KMP() { ll l1 = s1.size(), l2 = s2.size(), i = 0, j = 0, res = 0; while (i < l1) { if (j == -1 || s1[i] == s2[j]) i++, j++; else j = nextt[j]; if (j == l2) res++, j = nextt[j];//匹配成功 } return res; } int main() { while (cin >> s1 >> s2) { getNext(s2); cout << KMP() << endl; } }