bzoj 1100
思路:好脑洞啊。。。 把边和角转化为字符串,然后用反串跑kmp。。。
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define pii pair<int, int> using namespace std; const int N = 1e5 + 7; const int M = 1e6 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 +7; int n, m; LL a[N << 2], b[N << 2]; int nx[N << 2]; struct Point { LL x, y; Point(LL x = 0, LL y = 0) { this->x = x; this->y = y; } Point operator - (const Point &rhs) const { return Point(x - rhs.x, y - rhs.y); } } p[N]; typedef Point Vector; LL dis(const Point &a, const Point &b) { return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y); } LL cross(Vector a, Vector b) { return a.x * b.y - a.y * b.x; } void getNext() { int k = 0; for(int i = 1; i < m; i++) { while(k > 0 && b[k] != b[i]) k = nx[k - 1]; if(b[k] == b[i]) k++; nx[i] = k; } } int kmp() { int k = 0, ans = 0; for(int i = 0; i < n; i++) { while(k > 0 && b[k] != a[i]) k = nx[k - 1]; if(b[k] == a[i]) k++; if(k == m) { ans++; k = nx[k - 1]; } } return ans; } int main(){ int T; scanf("%d", &T); while(T--) { scanf("%d", &n); for(int i = 0; i < n; i++) { scanf("%lld%lld", &p[i].x, &p[i].y); } for(int i = 0; i < n; i++) { Vector v1 = p[(i + 1) % n] - p[i]; Vector v2 = p[(i - 1 + n) % n] - p[i]; a[i << 1] = cross(v1, v2); } for(int i = 0; i < n; i++) { a[i << 1 | 1] = dis(p[i], p[(i + 1) % n]); } for(int i = 2 * n; i < 4 * n; i++) { a[i] = a[i - 2 * n]; } m = 2 * n; n = 4 * n; for(int i = 0; i < m; i++) { b[i] = a[i]; } reverse(b, b + m); getNext(); printf("%d\n", kmp()); } return 0; } /* */