第六周 8.23-8.29

8.23

POJ 3311 Hie with the Pie

TSP问题。

先跑一遍Floyd。再状压dp。

dp[i][j]表示经过集合i的点最后到达j的最短距离。

转移:取集合i中任意一点j。如果i中只有j。dp[i][j]=dist[i][j]。

如果i中还有其他点k。dp[i][j]=min(dp[i\{j}][k]+dist[k][j])。

 1 # include <iostream>
 2 # include <cstdio>
 3 # include <algorithm>
 4 using namespace std;
 5 # define INF 1000000000
 6 int dist[11][11],dp[1<<10][10];
 7 
 8 int main(void)
 9 {
10     int n;
11     while(~scanf("%d",&n)&&n)
12     {
13         for(int i=0;i<=n;i++)
14             for(int j=0;j<=n;j++)
15                 scanf("%d",&dist[i][j]);
16         for(int k=0;k<=n;k++)
17             for(int i=0;i<=n;i++)
18                 for(int j=0;j<=n;j++)
19                     dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]);
20         for(int i=1;i<(1<<n);i++)
21         {
22             for(int j=1;j<=n;j++)
23             {
24                 if(i==(1<<(j-1))) dp[i][j]=dist[0][j];
25                 else if(i&(1<<(j-1)))
26                 {
27                     dp[i][j]=INF;
28                     for(int k=1;k<=n;k++)
29                     {
30                         if(k==j) continue;
31                         if(i&(1<<(k-1))) dp[i][j]=min(dp[i][j],dp[i^(1<<(j-1))][k]+dist[k][j]);
32                     }
33                 }
34             }
35         }
36         int ans=INF;
37         for(int i=1;i<=n;i++) ans=min(ans,dp[(1<<n)-1][i]+dist[i][0]);
38         printf("%d\n",ans);
39     }
40     return 0;
41 }
Aguin

 

UVA 11205 The broken pedometer

题意:在P列中选择最少的列。使得每行排列都不同。

二进制枚举选择列的所有情况。

判断排列是否相同可以采用给每一位按二进制赋权。用一个一维数组标记。

如果枚举的排列选择的列数大于当前答案直接剪掉。

 1 # include <iostream>
 2 # include <cstdio>
 3 # include <cstring>
 4 using namespace std;
 5 int a[101][16],vis[1<<15];
 6 
 7 int main(void)
 8 {
 9     int T ; cin>>T;
10     while(T--)
11     {
12         int P,N;
13         scanf("%d%d",&P,&N);
14         for(int i=1;i<=N;i++)
15             for(int j=1;j<=P;j++)
16                 scanf("%d",&a[i][j]);
17         int ans=P;
18         for(int i=1;i<(1<<P);i++)
19         {
20             int ok=1,tem=0;
21             for(int j=1;j<=i;j<<=1) if(i&j) tem++;
22             if(tem>=ans) continue;
23             memset(vis,0,sizeof(vis));
24             for(int j=1;j<=N;j++)
25             {
26                 int cnt=0;
27                 for(int k=1;k<=P;k++)
28                     if((i&(1<<(k-1)))&&a[j][k]) cnt+=1<<(k-1);
29                 if(vis[cnt]) {ok=0;break;}
30                 vis[cnt]=1;
31             }
32             if(ok) ans=tem;
33         }
34         printf("%d\n",ans);
35     }
36     return 0;
37 }
Aguin

 

HDU 3714 Error Curves

学习了三分的方法。挺好写的。

 1 # include <iostream>
 2 # include <cstdio>
 3 # include <cmath>
 4 # include <algorithm>
 5 using namespace std;
 6 int n,a[10010],b[10010],c[10010];
 7 
 8 double cal(double x)
 9 {
10     double ret=-1e10;
11     for(int i=1;i<=n;i++)
12     {
13         double tem=a[i]*x*x+b[i]*x+c[i];
14         ret=max(ret,tem);
15     }
16     return ret;
17 }
18 
19 int main(void)
20 {
21     int T; cin>>T;
22     while(T--)
23     {
24         scanf("%d",&n);
25         for(int i=1;i<=n;i++) scanf("%d%d%d",a+i,b+i,c+i);
26         double l=0,r=1000,ans;
27         while(1)
28         {
29             double m1=(2*l+r)/3,m2=(l+2*r)/3;
30             double t1=cal(m1),t2=cal(m2);
31             if(fabs(t2-t1)<1e-6) {ans=t1;break;}
32             if(t1>t2) l=m1;
33             else r=m2;
34         }
35         printf("%.4lf\n",ans);
36     }
37     return 0;
38 }
Aguin

 

HDU 1172 猜数字

暴力举四位数。当且仅当只有一个数字符合条件的时候有解。

判断的时候注意不要计重了。

 1 # include <iostream>
 2 # include <cstdio>
 3 using namespace std;
 4 int a[101],b[101],c[101];
 5 
 6 int main(void)
 7 {
 8     int N;
 9     while(~scanf("%d",&N)&&N)
10     {
11         for(int i=1;i<=N;i++) scanf("%d%d%d",a+i,b+i,c+i);
12         int ans=0;
13         for(int i=1000;i<=9999;i++)
14         {
15             int d1[4],d2[4];
16             d1[3]=i;
17             for(int j=2;j>=0;j--)
18             {
19                 d1[j]=d1[j+1]/10;
20                 d1[j+1]-=10*d1[j];
21             }
22             int flag=1;
23             for(int j=1;j<=N;j++)
24             {
25                 d2[3]=a[j];
26                 for(int k=2;k>=0;k--)
27                 {
28                     d2[k]=d2[k+1]/10;
29                     d2[k+1]-=10*d2[k];
30                 }
31                 int temb=0,temc=0;
32                 for(int k=0;k<4;k++)
33                     if(d1[k]==d2[k]) temc++;
34                 for(int k=0;k<4;k++)
35                     for(int l=0;l<4;l++)
36                         if(d1[k]==d2[l])
37                             {d2[l]=-1;temb++;break;}
38                 if(temb!=b[j]||temc!=c[j]) {flag=0;break;}
39             }
40             if(flag)
41             {
42                 if(ans) {ans=0;break;}
43                 else ans=i;
44             }
45         }
46         if(ans) printf("%d\n",ans);
47         else puts("Not sure");
48     }
49     return 0;
50 }
Aguin

 

CF 276D Little Girl and Maximum XOR

神奇。找a和b最高不同位即可。

 1 # include <iostream>
 2 # include <cstdio>
 3 using namespace std;
 4 typedef long long LL;
 5 
 6 int main(void)
 7 {
 8     LL a,b;
 9     scanf("%I64d%I64d",&a,&b);
10     LL cnt=0,x=a^b;
11     while(x){cnt++; x>>=1;}
12     printf("%I64d\n",((LL)1<<cnt)-1);
13     return 0;
14 }
Aguin

 

HDU 1045 Fire Net

dfs水果。

 1 # include <iostream>
 2 # include <cstdio>
 3 using namespace std;
 4 char map[5][5];
 5 int n,ans,tem;
 6 
 7 void dfs(int x,int y)
 8 {
 9     if(map[x][y]=='.')
10     {
11         int l=1,r=1,u=1,d=1;
12         for(int i=1;i<x;i++)
13         {    
14             if(map[i][y]=='@') u=0;
15             if(map[i][y]=='X') u=1;
16         }
17         for(int i=n;i>x;i--)
18         {    
19             if(map[i][y]=='@') d=0;
20             if(map[i][y]=='X') d=1;
21         }
22         for(int i=1;i<y;i++)
23         {    
24             if(map[x][i]=='@') l=0;
25             if(map[x][i]=='X') l=1;
26         }
27         for(int i=n;i>y;i--)
28         {    
29             if(map[x][i]=='@') r=0;
30             if(map[x][i]=='X') r=1;
31         }
32         if(u&&d&&l&&r)
33         {
34             map[x][y]='@'; tem++;
35             ans=max(ans,tem);
36             if(x<n||y<n)dfs(x+(y+1>n?1:0),y+1>n?1:y+1);
37             map[x][y]='.'; tem--;
38         }
39     }
40     if(x<n||y<n) dfs(x+(y+1>n?1:0),y+1>n?1:y+1);
41     return;
42 }
43 
44 int main(void)
45 {
46     while(~scanf("%d",&n)&&n)
47     {
48         for(int i=1;i<=n;i++)
49             scanf("%s",map[i]+1);
50         tem=ans=0;
51         dfs(1,1);
52         printf("%d\n",ans);
53     }
54     return 0;
55 }
Aguin

 

CF 433B Kolya and Tandem Repeat

暴力水果。

 1 # include <iostream>
 2 # include <cstdio>
 3 # include <cstring>
 4 using namespace std;
 5 char s[222];
 6 
 7 int main(void)
 8 {
 9     scanf("%s",s+1);
10     int k; scanf("%d",&k);
11     int len=strlen(s+1);
12     for(int i=(len+k)/2;i>=0;i--)
13     {
14         int flag;
15         for(int j=1;j+2*i-1<=len+k;j++)
16         {
17             flag=1;
18             for(int k=j;k<j+i;k++)
19                 if(k<=len&&k+i<=len&&s[k]!=s[k+i])
20                     {flag=0;break;}
21             if(flag) break;
22         }
23         if(flag) {printf("%d\n",2*i);break;}
24     }
25     return 0;
26 }
Aguin

 

8.24

CF 193B Xor

暴搜。

一个剪枝是连续偶数次xor相当于没做。直接跳过。

 1 # include <iostream>
 2 # include <cstdio>
 3 # include <cstring>
 4 # include <algorithm>
 5 using namespace std;
 6 typedef long long LL;
 7 const LL INF=(LL)1e18;
 8 LL ans,a[40],b[40],k[40],p[40],cur[40];
 9 int n,u,r;
10 
11 LL cal(void)
12 {
13     LL ret=0;
14     for(int i=1;i<=n;i++) ret+=cur[i]*k[i];
15     return ret;
16 }
17 
18 void dfs(int step,int op)
19 {
20     if(step==u){ans=max(ans,cal());return;}
21     else if((u-step)%2==0) ans=max(ans,cal());
22     LL t[40];
23     for(int i=1;i<=n;i++) t[i]=cur[p[i]]+r;
24     if(op==2)
25     {
26         for(int i=1;i<=n;i++) cur[i]^=b[i];
27         dfs(step+1,1);
28     }
29     memcpy(cur,t,sizeof(cur));
30     dfs(step+1,2);
31     return;
32 }
33 
34 int main(void)
35 {
36     scanf("%d%d%d",&n,&u,&r);
37     for(int i=1;i<=n;i++) scanf("%I64d",a+i);
38     for(int i=1;i<=n;i++) scanf("%I64d",b+i);
39     for(int i=1;i<=n;i++) scanf("%I64d",k+i);
40     for(int i=1;i<=n;i++) scanf("%I64d",p+i);
41     memcpy(cur,a,sizeof(cur));
42     ans=-INF; dfs(0,2);
43     printf("%I64d\n",ans);
44     return 0;
45 }
Aguin

 

POJ 1753 Flip Game

和牛牛翻牌子一样。

二进制枚举第一行的情况。

 1 # include <iostream>
 2 # include <cstdio>
 3 # include <cstring>
 4 # include <algorithm>
 5 using namespace std;
 6 int step[][2]={{0,1},{0,-1},{1,0},{-1,0}};
 7 int org[5][5],map[5][5],ans;
 8 
 9 bool in(int i,int j)
10 {
11     return i&&i<5&&j&&j<5;
12 }
13 
14 void Flip(int x,int y)
15 {
16     map[x][y]=1-map[x][y];
17     for(int i=0;i<4;i++)
18     {
19         int xx=x+step[i][0],yy=y+step[i][1];
20         if(in(xx,yy)) map[xx][yy]=1-map[xx][yy];
21     }
22     return;
23 }
24 
25 void judge(int i,int c)
26 {
27     memcpy(map,org,sizeof(map));
28     int cnt=0;
29     for(int j=0;j<4;j++)
30         if((1<<j)&i) {Flip(1,j+1);cnt++;}
31     for(int j=2;j<=4;j++)
32         for(int k=1;k<=4;k++)
33             if(map[j-1][k]!=c) {Flip(j,k);cnt++;}
34     int ok=1;
35     for(int j=1;j<=4;j++) if(map[4][j]!=c) {ok=0;break;}
36     if(ok) ans=min(ans,cnt);
37     return;    
38 }
39 
40 int main(void)
41 {
42     for(int i=1;i<=4;i++)
43     {
44         char s[10];
45         scanf("%s",s+1);
46         for(int j=1;j<=4;j++)
47             org[i][j]=(s[j]=='b')?1:0;
48     }
49     ans=20;
50     for(int i=0;i<16;i++)
51     {
52         judge(i,0);
53         judge(i,1);
54     }
55     if(ans<20) printf("%d\n",ans);
56     else puts("Impossible");
57     return 0;
58 }
Aguin

 

CF 442A Borya and Hanabi

神奇方法。

把牌看成二维点。

枚举所有hint的可能。

每一个hint加一条线。

先去掉在交点处的点。再去掉一条直线上唯一的点。

最后如果剩余1个或者不剩余就可行。

 1 # include <iostream>
 2 # include <cstdio>
 3 # include <cstring>
 4 # include <algorithm>
 5 # include <set>
 6 using namespace std;
 7 typedef pair<int,int> pii;
 8 int map[6][6],cpy[6][6],mark[6];
 9 char alp[]=" RGBYW";
10 set<pii> S,tem;
11 
12 int id(char c)
13 {
14     for(int i=1;i<=5;i++) if(c==alp[i]) return i;
15 }
16 
17 int main(void)
18 {
19     int n; scanf("%d",&n);
20     for(int i=1;i<=n;i++)
21     {
22         char s[5]; scanf("%s",s);
23         int a=id(s[0]),b=s[1]-'0';
24         S.insert(pii(a,b));
25         map[a][b]=1;
26     }
27     int ans=10;
28     for(int i=0;i<(1<<5);i++)
29     {
30         for(int j=0;j<(1<<5);j++)
31         {
32             int num=0; tem=S;
33             for(int k=1;k<(1<<5);k<<=1) num+=(k&i?1:0)+(k&j?1:0);
34             if(num>=ans) continue;
35             memset(mark,0,sizeof(mark));
36             memcpy(cpy,map,sizeof(map));
37             for(int k=1;k<=5;k++) if((1<<(k-1))&i) mark[k]=1;
38             for(int k=1;k<=5;k++) if((1<<(k-1))&j)
39             {
40                 for(int l=1;l<=5;l++) if(mark[l]&&cpy[l][k])
41                 {
42                     cpy[l][k]=0;
43                     tem.erase(pii(l,k));
44                 }
45                 int cnt=0,pos;
46                 for(int l=1;l<=5;l++) if(cpy[l][k]) {cnt++;pos=l;}
47                 if(cnt==1)
48                 {
49                     cpy[pos][k]=0;
50                     tem.erase(pii(pos,k));
51                 }
52             }
53             for(int k=1;k<=5;k++) if(mark[k])
54             {
55                 int cnt=0,pos;
56                 for(int l=1;l<=5;l++) if(cpy[k][l]) {cnt++;pos=l;}
57                 if(cnt==1)
58                 {
59                     cpy[k][pos]=0;
60                     tem.erase(pii(k,pos));
61                 }
62             }
63             if(tem.size()<=1) ans=min(ans,num);
64         }
65     }
66     printf("%d\n",ans);
67     return 0;
68 }
Aguin

 

CF 430B Balls Game

枚举起点。模拟祖玛。

 1 # include <iostream>
 2 # include <cstdio>
 3 # include <algorithm>
 4 using namespace std;
 5 int c[101];
 6 
 7 int main(void)
 8 {
 9     int n,k,x,ans=0;
10     scanf("%d%d%d",&n,&k,&x);
11     for(int i=1;i<=n;i++) scanf("%d",c+i);    
12     for(int i=1;i<n;i++)
13     {
14         if(c[i-1]!=x&&c[i]==x&&c[i+1]==x)
15         {
16             int l=i-1,r=i+2;
17             while(l>0&&r<=n)
18             {
19                 if(c[l]!=c[r]) break;
20                 int cur=c[l];
21                 if(l>1&&c[l-1]==cur||r<n&&c[r+1]==cur)
22                 {
23                     while(c[r]==cur) r++;
24                     while(c[l]==cur) l--;
25                 }
26                 else break;
27             }
28             ans=max(ans,r-l-1);
29         }
30     }
31     printf("%d\n",ans);
32     return 0;
33 }
Aguin

 

HDU 4717 The Moving Points

因为昨天刚做了个三分印象深刻。于是三分水果。

 1 # include <iostream>
 2 # include <cstdio>
 3 # include <cmath>
 4 # include <algorithm>
 5 using namespace std;
 6 int n;
 7 
 8 struct point
 9 {
10     int x,y,vx,vy;
11     double xx,yy;
12 }p[301];
13 
14 double dis(int i,int j)
15 {
16     return sqrt(pow(p[i].xx-p[j].xx,2)+pow(p[i].yy-p[j].yy,2));
17 }
18 
19 double cal(double t)
20 {
21     for(int i=1;i<=n;i++)
22     {
23         p[i].xx=p[i].x+p[i].vx*t;
24         p[i].yy=p[i].y+p[i].vy*t;
25     }
26     double ret=0;
27     for(int i=1;i<=n;i++)
28         for(int j=1;j<=n;j++)
29             ret=max(ret,dis(i,j));
30     return ret;
31 }
32 
33 int main(void)
34 {
35     int T;cin>>T;
36     for(int kase=1;kase<=T;kase++)
37     {
38         scanf("%d",&n);
39         for(int i=1;i<=n;i++)
40             scanf("%d%d%d%d",&p[i].x,&p[i].y,&p[i].vx,&p[i].vy);
41         double l=0,r=1000000000,ans;
42         while(r-l>1e-5)
43         {
44             double m1=(2*l+r)/3,m2=(l+2*r)/3;
45             double t1=cal(m1),t2=cal(m2);
46             if(t1<t2) r=m2;
47             else l=m1;
48             ans=t1;
49         }
50         printf("Case #%d: %.2lf %.2lf\n",kase,l,ans);
51     }
52     return 0;
53 }
Aguin

 

POJ 2965 The Pilots Brothers' refrigerator

首先每个格子最多翻一次。翻偶数次相当于不翻。奇数次相当于翻一次。

如果要让一个格子(i,j)翻。其他格子不动。只要翻(i,j)后再翻一遍行标为i的其他格子与列标为j的其他格子。

这样只要处理每个-格子。做上面的操作。统计每个格子最后翻的次数奇偶即可。

 1 # include <iostream>
 2 # include <cstdio>
 3 using namespace std;
 4 int map[6][6];
 5 
 6 int main(void)
 7 {
 8     for(int i=1;i<=4;i++)
 9     {
10         char s[10]; scanf("%s",s+1);
11         for(int j=1;j<=4;j++) if(s[j]=='+')
12         {
13             for(int k=1;k<=4;k++) map[i][k]++;
14             for(int k=1;k<=4;k++) map[k][j]++;
15             map[i][j]--;
16         }
17     }
18     int ans=0;
19     for(int i=1;i<=4;i++)
20         for(int j=1;j<=4;j++)
21             if(map[i][j]%2) ans++;
22     printf("%d\n",ans);
23     for(int i=1;i<=4;i++)
24         for(int j=1;j<=4;j++)
25             if(map[i][j]%2)
26                 printf("%d %d\n",i,j);
27     return 0;
28 }
Aguin

 

ZOJ 1008 Gnome Tetravex

直接暴力T。

偷看题解一个优化。把相同的块合在一起就可以了。

表示不服。毕竟块有10000种。而每个图最多只有25个块。

IO挺恶心还PE了两发才过。

 1 # include <iostream>
 2 # include <cstdio>
 3 # include <cstring>
 4 using namespace std;
 5 int n,cur,squ[26][4],map[6][6],cnt[26];
 6 
 7 bool dfs(int x,int y)
 8 {
 9     if(x>n) return true;
10     for(int i=1;i<=n*n;i++) if(cnt[i])
11     {
12         if(x>1&&squ[map[x-1][y]][2]!=squ[i][0]) continue;
13         if(y>1&&squ[map[x][y-1]][1]!=squ[i][3]) continue;
14         map[x][y]=i; cnt[i]--;
15         if(dfs(x+(y+1>n?1:0),y+1>n?1:y+1)) return true;
16         map[x][y]=0; cnt[i]++;
17     }
18     return false;
19 }
20 
21 int main(void)
22 {
23     int kase=0;
24     while(~scanf("%d",&n)&&n)
25     {
26         memset(cnt,0,sizeof(cnt));
27         cur=0;
28         for(int i=1;i<=n*n;i++)
29         {
30             int u,r,d,l,same=0;
31             scanf("%d%d%d%d",&u,&r,&d,&l);
32             for(int j=1;j<=cur;j++)
33                 if(squ[j][0]==u&&squ[j][1]==r&&squ[j][2]==d&&squ[j][3]==l)
34                     {cnt[j]++;same=1;}
35             if(same) continue;
36             cur++; cnt[cur]=1;
37             squ[cur][0]=u; squ[cur][1]=r; squ[cur][2]=d; squ[cur][3]=l;
38         }
39         if(kase) puts("");
40         printf("Game %d: ",++kase);
41         puts(dfs(1,1)?"Possible":"Impossible");
42     }
43     return 0;
44 }
Aguin

 

找的两份暴力菜切完了。换换口味。回校前学点新东西。

 

8.25

看KMP。

8.26

HDU 1711 Number Sequence

已经无力吐槽了。贴板。

 1 # include <iostream>
 2 # include <cstdio>
 3 using namespace std;
 4 int a[1000100],b[10100];
 5 int n,m,Next[10100];
 6 
 7 void getNext(void)
 8 {        
 9     Next[0]=Next[1]=0;
10     for(int i=1;i<m;i++)
11     {
12         int j=Next[i];
13         while(j&&b[i]!=b[j]) j=Next[j];
14         Next[i+1]=b[i]==b[j]?j+1:0;    
15     }
16     return;
17 }
18 
19 bool KMP(void)
20 {
21     getNext();
22     int j=0;    
23     for(int i=0;i<n;i++)
24     {
25         while(j&&b[j]!=a[i]) j=Next[j];
26         if(b[j]==a[i]) j++;
27         if(j==m) {printf("%d\n",i-m+2);return true;}
28     }
29     return false;
30 }
31 
32 int main(void)
33 {
34     int T;cin>>T;
35     while(T--)
36     {
37         scanf("%d%d",&n,&m);
38         for(int i=0;i<n;i++) scanf("%d",a+i);
39         for(int i=0;i<m;i++) scanf("%d",b+i);
40         if(KMP()) continue;
41         printf("-1\n");
42     }
43     return 0;
44 }
Aguin

 

抄了个拓展KMP板。没找到验板题。拿上面那题小测好了。

 1 # include <iostream>
 2 # include <cstdio>
 3 # include <algorithm>
 4 using namespace std;
 5 int a[1000100],ex[1000100];
 6 int b[10100],Next[10100];
 7 int n,m;
 8 
 9 void getNext(void)
10 {
11     int P=1,j; Next[0]=m;
12     for(int i=Next[1]=0;i<m-1&&b[i]==b[i+1];) Next[1]=++i;
13     for(int i=2;i<m;i++)
14     {
15         if(Next[i-P]+i<Next[P]+P) Next[i]=Next[i-P];
16         else
17         {
18             j=max(Next[P]+P-i,0);
19             while(i+j<m&&b[j]==b[j+i]) j++;
20             Next[i]=j; P=i;
21         }
22     }
23     return;    
24 }
25 
26 void exKMP(void)
27 {
28     getNext();
29     int j,P=0;
30     for(int i=ex[0]=0;i<m&&a[i]==b[i];) ex[0]=++i;
31     for(int i=1;i<n;i++)
32     {
33         if(Next[i-P]+i<ex[P]+P) ex[i]=Next[i-P];
34         else
35         {
36             j=max(ex[P]+P-i,0);
37             while(i+j<n&&j<m&&a[j+i]==b[j]) j++;
38             ex[i]=j; P=i;
39         }
40     }
41     return;
42 }
43 
44 int main(void)
45 {
46     int T; cin>>T;
47     while(T--)
48     {
49         scanf("%d%d",&n,&m);
50         for(int i=0;i<n;i++) scanf("%d",a+i);
51         for(int i=0;i<m;i++) scanf("%d",b+i);
52         exKMP();
53         int ok=0;
54         for(int i=0;i<n;i++)
55             if(ex[i]==m) {printf("%d\n",i+1);ok=1;break;}
56         if(!ok) puts("-1");
57     }
58     return 0;
59 }
Aguin

 

HDU 1686 Oulipo

又一裸KMP。然而完成一次匹配后要滑回Next[j]。

 1 # include <iostream>
 2 # include <cstdio>
 3 # include <cstring>
 4 using namespace std;
 5 char a[1000100],b[1000100];
 6 int n,m,ans,Next[1000100];
 7 
 8 void getNext(void)
 9 {        
10     Next[0]=Next[1]=0;
11     for(int i=1;i<m;i++)
12     {
13         int j=Next[i];
14         while(j&&b[i]!=b[j]) j=Next[j];
15         Next[i+1]=b[i]==b[j]?j+1:0;    
16     }
17     return;
18 }
19 
20 void KMP(void)
21 {
22     getNext();
23     int j=0;    
24     for(int i=0;i<n;i++)
25     {
26         while(j&&b[j]!=a[i]) j=Next[j];
27         if(b[j]==a[i]) j++;
28         if(j==m) {ans++;j=Next[j];}
29     }
30     return;
31 }
32 
33 int main(void)
34 {
35     int T;cin>>T;
36     while(T--)
37     {
38         scanf("%s%s",b,a);
39         m=strlen(b),n=strlen(a);
40         ans=0; KMP();
41         printf("%d\n",ans);
42     }
43     return 0;
44 }
Aguin

 

8.27

HDU 2087 剪花布条

裸KMP。与上题区分。匹配完j重置0。

 1 # include <iostream>
 2 # include <cstdio>
 3 # include <cstring>
 4 using namespace std;
 5 char a[1000100],b[1000100];
 6 int n,m,ans,Next[1000100];
 7 
 8 void getNext(void)
 9 {        
10     Next[0]=Next[1]=0;
11     for(int i=1;i<m;i++)
12     {
13         int j=Next[i];
14         while(j&&b[i]!=b[j]) j=Next[j];
15         Next[i+1]=b[i]==b[j]?j+1:0;    
16     }
17     return;
18 }
19 
20 void KMP(void)
21 {
22     getNext();
23     int j=0;    
24     for(int i=0;i<n;i++)
25     {
26         while(j&&b[j]!=a[i]) j=Next[j];
27         if(b[j]==a[i]) j++;
28         if(j==m) {ans++;j=0;}
29     }
30     return;
31 }
32 
33 int main(void)
34 {
35     while(~scanf("%s",a))
36     {
37         if(a[0]=='#') break;
38         scanf("%s",b);
39         m=strlen(b),n=strlen(a);
40         ans=0; KMP();
41         printf("%d\n",ans);
42     }
43     return 0;
44 }
Aguin

 

由于不放心。重新抄了套MP/KMP板。

MP板和之前的除了Next[0]=-1其余都一样。

KMP板在速度上并没感觉快。性质反而丢失了。

 1 void mp_Next(void)
 2 {
 3     int i=0,j=Next[0]=-1;
 4     while(i<m)
 5     {
 6         while(-1!=j&&b[i]!=b[j])j=Next[j];
 7         Next[++i]=++j;
 8     }
 9     return;
10 }
11 
12 void kmp_Next(void)
13 {
14     int i=0,j=Next[0]=-1;
15     while(i<m)
16     {
17         while(-1!=j&&b[i]!=b[j])j=Next[j];
18         if(b[++i]==b[++j]) Next[i]=Next[j];
19         else Next[i]=j;
20     }
21     return;
22 }
23 
24 void KMP(void)
25 {
26     int i=0,j=0;
27     mp_Next();
28     while(i<n)
29     {
30         while(-1!=j&&a[i]!=b[j])j=Next[j];
31         i++;j++;
32         if(j==m){/*爱干嘛干嘛*/}
33     }
34     return;
35 }
Aguin

 

HDU 3746 Cyclic Nacklace

运用了Next数组的一个性质

可以求循环节。

 1 # include <iostream>
 2 # include <cstdio>
 3 # include <cstring>
 4 using namespace std;
 5 char b[100100];
 6 int m,Next[100100];
 7 
 8 void getNext(void)
 9 {        
10     Next[0]=Next[1]=0;
11     for(int i=1;i<m;i++)
12     {
13         int j=Next[i];
14         while(j&&b[i]!=b[j]) j=Next[j];
15         Next[i+1]=b[i]==b[j]?j+1:0;    
16     }
17     return;
18 }
19 
20 int main(void)
21 {
22     int T; cin>>T;
23     while(T--)
24     {
25         scanf("%s",b);
26         m=strlen(b);
27         getNext();
28         int t=m-Next[m];
29         if(t!=m&&m%t==0)printf("0\n");
30         else printf("%d\n",t-m%t);
31     }
32     return 0;
33 }
Aguin

 

HDU 1358 Period

题意:求能分解成循环的前缀。

学了上面的性质就很好做了。

 1 # include <iostream>
 2 # include <cstdio>
 3 # include <cstring>
 4 using namespace std;
 5 char b[1000100];
 6 int m,Next[1000100];
 7 
 8 void getNext(void)
 9 {        
10     Next[0]=Next[1]=0;
11     for(int i=1;i<m;i++)
12     {
13         int j=Next[i];
14         while(j&&b[i]!=b[j]) j=Next[j];
15         Next[i+1]=b[i]==b[j]?j+1:0;    
16     }
17     return;
18 }
19 
20 int main(void)
21 {
22     int kase=0;
23     while(~scanf("%d",&m)&&m)
24     {
25         scanf("%s",b);
26         getNext();
27         printf("Test case #%d\n",++kase);
28         for(int i=1;i<=m;i++)
29         {
30             int t=i-Next[i];
31             if(i%t==0&&i/t>1) printf("%d %d\n",i,i/t);
32         }
33         puts("");
34     }
35     return 0;
36 }
Aguin

 

HUST 1010 The Minimum Length

从后往前找第一个完整循环的循序节就是答案。

 1 # include <iostream>
 2 # include <cstdio>
 3 # include <cstring>
 4 using namespace std;
 5 char b[1000100];
 6 int m,Next[1000100];
 7 
 8 void getNext(void)
 9 {        
10     Next[0]=Next[1]=0;
11     for(int i=1;i<m;i++)
12     {
13         int j=Next[i];
14         while(j&&b[i]!=b[j]) j=Next[j];
15         Next[i+1]=b[i]==b[j]?j+1:0;    
16     }
17     return;
18 }
19 
20 int main(void)
21 {
22     while(~scanf("%s",&b))
23     {
24         m=strlen(b);
25         getNext();
26         for(int i=m;;i--)
27         {
28             int t=i-Next[i];
29             if(i%t==0) {printf("%d\n",t);break;}
30         }
31     }
32     return 0;
33 }
Aguin

 

POJ 2406 Power Strings

能拆成小循环就拆。不能就是1。

 1 # include <iostream>
 2 # include <cstdio>
 3 # include <cstring>
 4 using namespace std;
 5 char b[1000100];
 6 int m,Next[1000100];
 7 
 8 void getNext(void)
 9 {        
10     Next[0]=Next[1]=0;
11     for(int i=1;i<m;i++)
12     {
13         int j=Next[i];
14         while(j&&b[i]!=b[j]) j=Next[j];
15         Next[i+1]=b[i]==b[j]?j+1:0;    
16     }
17     return;
18 }
19 
20 int main(void)
21 {
22     while(~scanf("%s",&b))
23     {
24         if(b[0]=='.') break;
25         m=strlen(b);
26         getNext();
27         int t=m-Next[m];
28         if(m%t!=0) puts("1");
29         else printf("%d\n",m/t);
30     }
31     return 0;
32 }
Aguin

 

POJ 2752 Seek the Name, Seek the Fame

顺Next数组反向找回去。

 1 # include <iostream>
 2 # include <cstdio>
 3 # include <cstring>
 4 using namespace std;
 5 char b[1000100];
 6 int m,Next[1000100];
 7 
 8 void getNext(void)
 9 {        
10     Next[0]=Next[1]=0;
11     for(int i=1;i<m;i++)
12     {
13         int j=Next[i];
14         while(j&&b[i]!=b[j]) j=Next[j];
15         Next[i+1]=b[i]==b[j]?j+1:0;    
16     }
17     return;
18 }
19 
20 void ans_print(int pos)
21 {
22     if(Next[pos]) ans_print(Next[pos]);
23     printf("%d ",pos);
24     return;
25 }
26 
27 int main(void)
28 {
29     while(~scanf("%s",&b))
30     {
31         m=strlen(b);
32         getNext();
33         ans_print(m);
34         puts("");
35     }
36     return 0;
37 }
Aguin

 

POJ 3080 Blue Jeans

因为挂在KMP专题里。所以就暴力水果了?

 1 # include <iostream>
 2 # include <cstdio>
 3 # include <cstring>
 4 using namespace std;
 5 char ans[70],tem[70];
 6 char DNA[20][70];
 7 
 8 int main(void)
 9 {
10     int T ; cin>>T;
11     while(T--)
12     {
13         int n; scanf("%d",&n);
14         memset(ans,0,sizeof(ans));
15         for(int i=1;i<=n;i++) scanf("%s",DNA[i]+1);
16         int yes=0;
17         for(int l=60;l>2;l--)
18         {
19             for(int s=1;s+l-1<=60;s++)
20             {
21                 memcpy(tem,DNA[1]+s,l*sizeof(char));
22                 tem[l]=0;
23                 int ok=1;
24                 for(int i=2;i<=n;i++)
25                     if(!strstr(DNA[i]+1,tem))
26                         {ok=0;break;}
27                 if(ok)
28                 {
29                     yes=1;
30                     if(!strlen(ans)||strcmp(ans,tem)>0)
31                         strcpy(ans,tem);
32                 }
33             }
34             if(yes) {printf("%s\n",ans);break;}
35         }
36         if(!yes) puts("no significant commonalities");
37     }
38     return 0;
39 }
Aguin

 

8.28

HDU 2594 Simpsons’ Hidden Talents

方便的想法是把两串连一起。找前后缀。

 1 # include <iostream>
 2 # include <cstdio>
 3 # include <cstring>
 4 # include <algorithm>
 5 using namespace std;
 6 char b[100100];
 7 int m,Next[100100];
 8 
 9 void getNext(void)
10 {        
11     Next[0]=Next[1]=0;
12     for(int i=1;i<m;i++)
13     {
14         int j=Next[i];
15         while(j&&b[i]!=b[j]) j=Next[j];
16         Next[i+1]=b[i]==b[j]?j+1:0;    
17     }
18     return;
19 }
20 
21 int main(void)
22 {
23     while(~scanf("%s",&b))
24     {
25         int n=strlen(b);
26         scanf("%s",b+n);
27         m=strlen(b);
28         getNext();
29         int ans=m;
30         while(ans>min(m-n,n)) ans=Next[ans];
31         if(ans)
32         {
33             for(int i=0;i<ans;i++) putchar(b[i]);
34             printf(" ");
35         }
36         printf("%d\n",ans);
37     }
38     return 0;
39 }
Aguin

 

8.29

滚回学校。

BC爆。

不补。

posted @ 2015-08-23 00:22  Aguin  阅读(292)  评论(0编辑  收藏  举报