【CodeForces - 471D 】【構造差分kmp】MUH and Cube Walls
阿新 • • 發佈:2018-11-19
題意:
給你一個數組A,再給你一個數組B,我們可以任意將陣列B整體增加或者減少值X(整數),我們可以進行修改值的操作無限次,每次我們要在陣列A中找尋有幾段和陣列B完全匹配的子段。
思路:
可以發現由於可以將這個區間的數整體增加或減少一個數,因此該題匹配的重點不再是對於某個點的匹配,而是相鄰點之間的差,因此我們需要維護一個差分陣列。
讓差分陣列進行匹配即可。
總結:
差分作為一個比較常用的方法,主要適用於一些涉及相鄰兩點的差的一些題目。
程式碼:
#include <cstdio> #include <iostream> #include <cstring> #include <algorithm> #define rep(i,a,b) for(int i = a; i <= b; i++) using namespace std; const int N = 1e6+100; int a[N],b[N],a1[N],b1[N]; int n,m; int nxt[N]; void get(int* s) { memset(nxt,0,sizeof nxt); int j = 0; int l = m; for(int i = 2;i <= l;i ++) { while(j && s[j+1] != s[i]) j = nxt[j]; if(s[j+1] == s[i]) j ++; nxt[i] = j; } } int find(int* s1,int* s2) //s2為子串 { get(s2); int j = 0; int cnt = 0; int l = m; int ll = n; int tmp = 0; for(int i = 1;i <= ll;i ++) { while(j && s1[i] != s2[j+1]) j = nxt[j]; if(s1[i] == s2[j+1]) j ++; if(j == l) cnt++,j = nxt[j]; } return cnt; } int main() { scanf("%d%d",&n,&m); rep(i,1,n) scanf("%d",&a[i]); rep(i,1,m) scanf("%d",&b[i]); if(m == 1) printf("%d\n",n); else if(n < m) printf("0\n"); else{ rep(i,2,n) a1[i-1] = a[i]-a[i-1]; rep(i,2,m) b1[i-1] = b[i]-b[i-1]; n--,m--; printf("%d\n",find(a1,b1)); } return 0; } /* 字串均從1開始編號 next[i] 表示 1~i 子串前後綴匹配的長度 迴圈節為 len-next[len] */ /* 11 4 3 4 5 6 7 8 9 10 11 12 13 2 3 4 5 */