• 第六周 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
    ",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
    ",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
    ",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
    ",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
    ",((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
    ",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
    ",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
    ",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
    ",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
    ",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
    ",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
    ",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
    ",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
    ",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
    ",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
    ");
    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
    ",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
    ",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
    ",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
    ");
    30         else printf("%d
    ",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
    ",++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
    ",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
    ",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
    ",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
    ",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
    ",ans);
    37     }
    38     return 0;
    39 }
    Aguin

    8.29

    滚回学校。

    BC爆。

    不补。

  • 相关阅读:
    JVM学习笔记-方法区(Method Area)
    JVM学习笔记-类型信息(Type Information)
    JVM学习笔记-常量池(Constant Pool)
    JVM学习笔记-字段信息(Field Information)
    hive schematool -initSchema -dbType mysql 报错
    flink error: Exception in thread "main" java.lang.NoClassDefFoundError
    python error: TypeError: cannot serialize '_io.TextIOWrapper' object
    multiprocessing.Pool 捕获error
    sysdig 安装与使用(转载)
    sonatype nexus简介(转)
  • 原文地址:https://www.cnblogs.com/Aguin/p/4751711.html
Copyright © 2020-2023  润新知