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 }
题目链接: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 }

浙公网安备 33010602011771号