137. 雪花雪花雪花 158. 项链

题目链接:https://www.acwing.com/problem/content/139/

思路:1. 转动相当于 接成环 枚举不同的开头,顺逆时针相当于把数组翻转 

所以  把原数组和翻转后的数组都求一个最小表示, 再取两者的最小表示最小值来作hash值

2.将所有数组排序 然后每次比较相邻是否相等即可 只要i-1 等于i 即可

注意的是二维数组的排序用下标来实现  最小表示法可以做到o n求出

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 const int maxn=1e5+10;
  4 const int mod=1e9+7;
  5 #define ll long long
  6 #define ull unsigned long long
  7 #define pi pair<int,ll>
  8 #define fi first
  9 #define sc second
 10 #define pb push_back
 11 
 12 int snows[maxn][6];
 13 int n,idx[maxn];
 14 
 15 bool cmp(int a[],int b[])// a<b
 16 {
 17     for(int i=0;i<6;i++)
 18     {
 19         if(a[i]>b[i]) return 0;
 20         else if(b[i]>a[i]) return 1;
 21     }
 22     return 0;
 23 }
 24 
 25 bool cmp2(int a,int b)
 26 {
 27     for(int i=0;i<6;i++)
 28     {
 29         if(snows[a][i]<snows[b][i]) return 1;
 30         else if(snows[a][i]>snows[b][i]) return 0;
 31     }
 32     return 0;
 33 }
 34 
 35 void getmin(int b[])// 求最小表示法  可以暴力  也可以o n
 36 {
 37     // 暴力
 38     /*int c[6];
 39     memset(c,0x3f,sizeof(c));
 40     int d[12];
 41     for(int i=0;i<12;i++) d[i]=b[i%6];
 42     for(int i=0;i<6;i++)
 43     {
 44         int tmp[6];
 45         for(int j=0;j<6;j++)
 46         {
 47             tmp[j]=d[i+j];
 48         }
 49         if(cmp(tmp,c))
 50         {
 51             for(int j=0;j<6;j++) c[j]=tmp[j];
 52         }
 53     }
 54 
 55     for(int i=0;i<6;i++) b[i]=c[i];*/
 56 
 57 
 58     int a[12];
 59     for(int i=0;i<12;i++) a[i]=b[i%6];
 60 
 61     int i=0,j=1,k;
 62     while(i<6&&j<6)
 63     {
 64         for(k=0;k<6&&a[i+k]==a[j+k];k++);
 65         if(k==6) break;
 66         if(a[i+k]>a[j+k])
 67         {
 68             i+=k+1;
 69             if(i==j) i++;
 70         }
 71         else
 72         {
 73             j+=k+1;
 74             if(i==j) j++;
 75         }
 76     }
 77 
 78     k=min(i,j);
 79     for(int i=0;i<6;i++) b[i]=a[i+k];
 80 
 81 
 82 }
 83 
 84 
 85 int main()
 86 {
 87     ios::sync_with_stdio(0);
 88     cin.tie(0);
 89     cin>>n;
 90     int snow[6],isnow[6];
 91     for(int i=0;i<n;i++)
 92     {
 93         for(int j=0,k=5;j<6;j++,k--)
 94         {
 95             cin>>snow[j];
 96             isnow[k]=snow[j];
 97         }
 98         getmin(snow);
 99         getmin(isnow);
100 
101         if(cmp(snow,isnow)) memcpy(snows[i],snow,sizeof snow);
102         else memcpy(snows[i],isnow,sizeof isnow);
103 
104         idx[i]=i;//二维数组要用下标来排序
105     }
106 
107     sort(idx,idx+n,cmp2);
108     int f=0;
109     for(int i=1;i<n;i++)
110     {
111         if(!cmp2(idx[i-1],idx[i])) f=1;
112     }
113 
114     if(f) cout<<"Twin snowflakes found."<<'\n';
115     else cout<<"No two snowflakes are alike."<<'\n';
116 
117 
118 
119 
120 
121 
122 }
View Code

 

题目链接:https://www.acwing.com/problem/content/160/

思路:o n求最小表示法   先将两个字符串复制一遍

然后用i=0 j=1 指向第一个和第二个 每次比较 大于的就i+=k+1 注意i==j的时候要i++

最后返回下标小的即为最小表示的下标起点

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=5e2+10;
 4 const int mod=1e9+7;
 5 #define ll long long
 6 #define ull unsigned long long
 7 #define pi pair<int,int>
 8 #define fi first
 9 #define sc second
10 #define pb push_back
11 
12 int n;
13 
14 int getmi(string s)
15 {
16     int i=0,j=1;
17     while(i<n&&j<n)
18     {
19         int k=0;
20         while(k<n&&s[i+k]==s[j+k]) k++;
21         if(s[i+k]>s[j+k]) i+=k+1;
22         else j+=k+1;
23         if(i==j) i++;
24     }
25     return min(i,j);
26 }
27 
28 int main()
29 {
30     ios::sync_with_stdio(false);
31     cin.tie(0);
32     string a,b;
33     cin>>a>>b;
34     n=a.size();
35     for(int i=0;i<n;i++) a+=a[i],b+=b[i];
36     int na=getmi(a),nb=getmi(b);
37     string ta=a.substr(na,n);
38     string tb=b.substr(nb,n);
39     if(ta==tb) cout<<"Yes"<<'\n'<<ta<<'\n';
40     else cout<<"No"<<'\n';
41 
42 
43 
44 
45 
46 
47 
48 
49 
50 
51 }
View Code

 

posted @ 2021-03-29 21:43  canwinfor  阅读(56)  评论(0)    收藏  举报