zjoi 2008 movement 无序运动 AC自动机

题意:

无序运动

【问题描述】

       D博士对物理有着深入的研究,经典物理、天体物理、量子物理都有着以他的名字命名的定理。最近D博士着迷于研究粒子运动的无规则性。对圣经深信不疑的他相信,上帝创造的任何事物必然是有序的、有理可循的,而不是无规则的、混沌的。

       经过长时间的研究,D博士找到了很多出现相当频繁的轨迹片断,他把这些轨迹片断储存在一个很大的数据库内。他需要你帮助他写一个程序,对于一个给出的粒子运动轨迹,统计数据库中每个轨迹片断的出现的次数。

       为清楚起见,我们定义一个粒子的轨迹为二维平面上的一个点列(P1, P2, … PN)。点列P的一个子列[i, j]定义为P中一段连续的子序列(Pi, Pi+1, … Pj)。点列P的一个子列[u, v]被称为点列Q = (Q1, Q2 … Qv-u+1)在P中的一次出现,当且仅当Q经过有限次的平移、旋转、翻转、放缩之后得到Q’满足Q’k = Pu+k-1(k = 1 … u – v + 1)。

 

对平面X-Y进行四种操作的解释

平移

设平移向量为(dx, dy),则任意点(x,y)平移后的结果为(x+dx, y+dy)

旋转

设旋转角为t,则任意点(x,y)旋转后的结果为

(x cos t – y sin t, x sin t + y cos t)

翻转

任意点(x,y) 翻转后的结果为(x, -y)

放缩

设放缩比例为p (p ≠ 0),则任意点(x,y)放缩后的结果为(px, py)

 

【输入文件】

       输入文件movement.in第一行两个整数NM,分别描述待处理的粒子运动轨迹的点列大小与数据库内的轨迹片断个数。

       接下来M行依次给出每个轨迹片断。每行先是一个正整数K,表示该轨迹片断点列的长度。然后2K个整数,依次描述点列中的K个点的横坐标与纵坐标。

       接下来一行2N个整数,依次描述待处理的粒子运动轨迹的点列中N个点的横坐标与纵坐标。

       注:输入中的每条轨迹中任意相邻两点不会相同。

【输出文件】

       输出文件movement.out应包含M行,依次给出每个片段在待处理运动轨迹中的出现次数。

 

这道题网上所有的数据和标程都是错的! 

 

思路:AC自动机 

每个点列 记三组特征值 两两边比 每个角的sin,cosn的值

AC自动机的字母个数比较多 用map

 

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cmath>
  4 #include<cstdio>
  5 #include<map>
  6 #include<algorithm>
  7 using namespace std;
  8 #define MAXN 400000+100
  9 #define EPS 1e-8
 10 struct point
 11 {
 12     double x,y;
 13     point() {}
 14     point(double x0,double y0):x(x0),y(y0){}
 15 };
 16 struct list
 17 {
 18     double sinn,cosn,edge;
 19 };
 20 struct node
 21 {
 22     list name;
 23     map<list,node*> next;
 24     node *failink,*father;
 25     int id;
 26     bool end;
 27 };
 28 node memo[MAXN];
 29 node *head;
 30 node *f[MAXN][2],*Q[MAXN];
 31 int n,m,top=0,label=0;
 32 int front,behind;
 33 int ans[MAXN],ans1[MAXN];
 34 point b[MAXN],a[MAXN];
 35 list p[MAXN];
 36 int dblcmp(double x)
 37 {
 38     if(fabs(x)<EPS) return 0;
 39     return (x>0) ? 1:-1;
 40 }
 41 point operator -(const point &A,const point &B)
 42 {
 43     return point(A.x-B.x,A.y-B.y);
 44 }
 45 double operator *(const point &A,const point &B)
 46 {
 47     return A.x*B.x+A.y*B.y;
 48 }
 49 bool operator <(list A,list B)
 50 {
 51     if(dblcmp(A.edge-B.edge)>0) return 0;
 52     if(dblcmp(A.edge-B.edge)<0) return 1;
 53     if(dblcmp(A.sinn-B.sinn)>0) return 0;
 54     if(dblcmp(A.sinn-B.sinn)<0) return 1;
 55     if(dblcmp(A.cosn-B.cosn)>0) return 0;
 56     if(dblcmp(A.cosn-B.cosn)<0) return 1;
 57     return 0;
 58 }
 59 double cross(point p1,point p2)
 60 {
 61     return p1.x*p2.y-p1.y*p2.x;
 62 }
 63 double dist(const point &A,const point &B)
 64 {
 65     return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
 66 }
 67 void insert(int num,int n,int multi)
 68 {
 69     node *t=head,*q;
 70     for(int i=1;i<=n;i++)
 71     {
 72         list x=p[i];
 73         x.sinn=p[i].sinn*multi;
 74         if(t->next[x]==NULL) 
 75         {
 76             q=&memo[top++]; q->name=x; q->father=t; q->id=++label; t->next[x]=q; 
 77         }
 78         t=t->next[x];
 79     }
 80     if(multi==1)
 81     f[num][0]=t;
 82     else f[num][1]=t;
 83 }
 84 
 85 void make_list(int n,int num)
 86 {
 87     bool w=0;
 88     for(int i=1;i<n-1;i++)
 89     {
 90         p[i].edge=dist(b[i+2],b[i+1])/dist(b[i+1],b[i]);
 91         p[i].sinn=cross(b[i+2]-b[i+1],b[i+1]-b[i])/dist(b[i+2],b[i+1])/dist(b[i+1],b[i]);
 92         p[i].cosn=(b[i+2]-b[i+1])*(b[i+1]-b[i])/dist(b[i+2],b[i+1])/dist(b[i+1],b[i]);
 93         if(dblcmp(p[i].sinn)!=0) w=1;
 94     }
 95     insert(num,n-2,1);
 96     if(w) insert(num,n-2,-1);
 97 }
 98 void set_failure_link()
 99 {
100     node *p,*t;
101     Q[front=behind=1]=head;
102     map<list,node*>::iterator i;
103     while(front<=behind)
104     {
105         p=Q[front++];
106         if(p->father==head) p->failink=head;
107         else if(p!=head)
108         {
109             list x=p->name;
110             for(t=p->father->failink;t!=NULL;t=t->failink)
111             {
112                 if(t->next[x]!=NULL)
113                 {
114                     p->failink=t->next[x]; break;
115                 }
116                 else if(t==head) 
117                 { 
118                     p->failink=t; break;
119                 }
120             }
121         }
122         for(i=p->next.begin();i!=p->next.end();i++)
123             Q[++behind]=i->second;
124     }
125 }
126 void search()
127 {
128     int i=1;
129     node *t;
130     list x;
131     t=head;
132     while(i<=n)
133     {   
134         x=p[i];     
135         if(t->next[x]==NULL)
136         {
137             if(t==head) i++;
138             else t=t->failink;
139             continue;
140         }
141         else t=t->next[x], i++;
142         ans[t->id]++;
143     }
144 }  
145 void compensate()
146 {
147     for(int i=behind;i>0;i--)
148         ans[Q[i]->failink->id]+=ans[Q[i]->id];
149 }
150 int main()
151 {
152     freopen("movement.in","r",stdin);
153     freopen("movement.out","w",stdout);
154     memset(f,0,sizeof(f));
155     memset(ans,0,sizeof(ans));
156     head=&memo[top++]; head->id=0; head->failink=head;
157     scanf("%d%d",&n,&m);
158     int i,j,k;
159     for(i=1;i<=m;i++)
160     {
161         scanf("%d",&k);
162         for(j=1;j<=k;j++)
163             scanf("%lf%lf",&b[j].x,&b[j].y);
164         if(k<=2) ans1[i]=n-k+1; 
165         else make_list(k,i);
166     }
167     set_failure_link();
168     for(i=1;i<=n;i++)
169         scanf("%lf%lf",&a[i].x,&a[i].y);
170     for(int i=1;i<n-1;i++)
171     {
172         p[i].edge=dist(a[i+2],a[i+1])/dist(a[i+1],a[i]);
173         p[i].sinn=cross(a[i+2]-a[i+1],a[i+1]-a[i])/dist(a[i+2],a[i+1])/dist(a[i+1],a[i]);
174         p[i].cosn=(a[i+2]-a[i+1])*(a[i+1]-a[i])/dist(a[i+2],a[i+1])/dist(a[i+1],a[i]);
175     }
176     n=n-2;
177     search();
178     compensate();
179     for(i=1;i<=m;i++)
180     {
181         if(f[i][0]==NULL) printf("%d\n",ans1[i]);
182         else 
183         {
184             if(f[i][1]!=NULL)
185                 printf("%d\n",ans[f[i][0]->id]+ans[f[i][1]->id]);
186             else printf("%d\n",ans[f[i][0]->id]);
187         }
188     }
189     return 0;
190 }

posted on 2012-04-15 18:22  myoi  阅读(805)  评论(1编辑  收藏  举报

导航