【codevs3945】 完美拓印
http://codevs.cn/problem/3945/ (题目链接)
题意
给出一个诡异的图形,再给出一个歪七扭八的线,问图形上下两条边与线的匹配→_→
Solution
前后求差然后KMP,这种数字的匹配还是KMP靠谱,hash太容易冲突了。
细节
注意可以上下翻转有4种匹配方式
代码
// codevs3945 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<vector> #include<cmath> #define LL long long #define inf 2147483640 #define Pi acos(-1.0) #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout); using namespace std; const int maxn=1000010; int next[maxn],t[maxn],p[maxn],a[maxn],b[maxn]; int n,m; void calnext() { next[1]=0; for (int i=2,j=0;i<=n;i++) { while (j && p[j+1]!=p[i]) j=next[j]; if (p[j+1]==p[i]) j++; next[i]=j; } } int kmp() { calnext(); int cnt=0; for (int j=0,i=1;i<=m;i++) { while (j && t[i]!=p[j+1]) j=next[j]; if (t[i]==p[j+1]) j++; if (j==n) cnt++,j=next[j]; } return cnt; } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) scanf("%d",&a[i]); for (int j=1;j<=m;j++) scanf("%d",&b[j]); if (n==1) {printf("%d",m*4);return 0;} n--,m--;int ans=0; for (int i=1;i<=n;i++) p[i]=a[i+1]-a[i]; for (int i=1;i<=m;i++) t[i]=b[i+1]-b[i]; ans+=kmp(); for (int i=1;i<=n;i++) p[i]=a[n-i+2]-a[n-i+1]; ans+=kmp(); for (int i=1;i<=n;i++) p[i]=0; ans+=2*kmp(); printf("%d\n",ans); return 0; }
This passage is made by MashiroSky.