2017西安交大ACM小学期 美妙音乐[差分KMP匹配]
生活随笔
收集整理的這篇文章主要介紹了
2017西安交大ACM小学期 美妙音乐[差分KMP匹配]
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
美妙音樂
發布時間: 2017年7月3日 13:14?? 最后更新: 2017年7月5日 13:47?? 時間限制: 500ms?? 內存限制: 128M
描述一段音樂是由若干個音符組成的,音樂中的某段音符稱為旋律。給定一首音樂,問某個旋律出現了多少次。注意:
(1)音樂中旋律是可以升調或降調的:例如 4 5 6和5 6 7是一個旋律;
(2)旋律不能重疊。
多組測試數據。
每組數據第一行有兩個正整數n,m。
第二行有n個整數,表示這段音樂。
第三行有m個整數,表示一段旋律。
輸入數據滿足音樂和旋律中的音符均為1到88之間的整數,即對應鋼琴里的88種音調。
n,m不超過5×105。
總輸入量∑n+∑m≤106。
對于每組數據輸出一行一個整數,表示答案。
樣例輸入1?復制 14 3 1 1 5 5 6 6 5 4 4 3 3 2 2 1 2 2 1 樣例輸出1 3題解:
對題目中給出的m個音符組成的的旋律做差分得到序列為(m-1)個相鄰差組成,記為模式
然后對整段音樂做差分,得到(n-1)個音符組成的序列,記為主串
對主串用模式進行KMP匹配,得到的匹配數目即是答案。
~!!!!!注意啦!題目中的旋律不能夠重疊,也就是說如果成功匹配到一個模式的時候,那么緊接著的下一個位置的差也不能用了,所以要i++;j = 0;
代碼:
#include <iostream> #include <cstdio> using namespace std; #define MAXN 2000001 int n,m; int a[MAXN]; int b[MAXN]; int s[MAXN]; int fail[MAXN]; void make_fail() {for (int i = 1, j = 0; i < m-1; i++){while (j && s[i] != s[j])j = fail[j - 1];if (s[i] == s[j])fail[i] = ++j;else fail[i] = 0;} } int search(int *str) {int ans = 0;for (int i = 0, j = 0; i < n-1; i++){while (j && str[i] != s[j])j = fail[j - 1];if (str[i] == s[j] && (++j == m-1)){ans++;i++;j = 0;}}return ans; } int main(){while(~scanf("%d%d",&n,&m)){for(int i = 0;i < n;i++){scanf("%d",&a[i]);}for(int i = 0;i < m;i++){scanf("%d",&b[i]);}if(m == 1){printf("%d\n",n);continue;}for(int i = 0;i < n-1;i++){a[i] = a[i+1] - a[i];}for(int i = 0;i < m-1;i++){s[i] = b[i+1] - b[i];}make_fail();int ans = search(a);printf("%d\n",ans);}return 0; }
總結
以上是生活随笔為你收集整理的2017西安交大ACM小学期 美妙音乐[差分KMP匹配]的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2017西安交大ACM小学期 有趣异或[
- 下一篇: 科大讯飞发布星火认知大模型 V3.0,号