标签:== title else 循环 vector string amp build print
A - Ananagrams
题意:输入一定量的单词构成词典(区分大小写),从词典中找出符合条件的单词,条件:单词转换成小写字母排序后与词典其他经此操作的单词不同(描述有点乱)。
Thinking:
这个题我最开始的感觉是构造hash函数来判重,然后并没有构造(查到)可以操作的函数,再然后就不会做了。网上给出了STL的方法,vector,map和string的排序,很好的解决了这道题的需要。
还有就是题目所说的lexicographic (case-sensitive) order 应该记下这个定义,这是集合和序的知识,虽然在这里只是基于ASCII排序即可。
1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #include <algorithm> 5 #include <map> 6 #include <cctype> 7 #include <string> 8 #include <algorithm> 9 using namespace std; 10 vector<string> v; 11 map<string, int> m; 12 string getlow(const string &x){ 13 string tmp = x; 14 for(int i=0; i<tmp.size(); i++){ 15 tmp[i] = tolower(tmp[i]); 16 } 17 sort(tmp.begin(), tmp.end()); 18 return tmp; 19 } 20 int main(){ 21 // freopen("in.txt", "r", stdin); 22 string s; 23 while(cin >> s){ 24 if(s[0] == ‘#‘)break; 25 v.push_back(s); 26 string tmp = getlow(s); 27 if(m.count(tmp)==0) m[tmp]=0; 28 m[tmp]++; 29 } 30 vector<string> ans; 31 for(int i=0; i<v.size(); i++){ 32 if(m[getlow(v[i])] == 1){ 33 ans.push_back(v[i]); 34 // cout << v[i] << " ------" << endl; 35 } 36 } 37 sort(ans.begin(), ans.end()); 38 for(int i=0; i<ans.size(); i++){ 39 cout << ans[i] << endl; 40 } 41 return 0; 42 }
C - Number Sequence
这个KMP(求位置)太明显了,不说了。
1 #include <cstdio> 2 #include <string> 3 #include <cctype> 4 using namespace std; 5 const int maxp = 10010, maxt = 1e6+10; 6 int f[maxp]; 7 int P[maxp], T[maxt]; 8 void getnext(int lenp){ 9 f[0] = f[1] = 0; 10 for(int i=1; i<lenp; i++){ 11 int j = f[i]; 12 while(j && P[i]!=P[j]) j=f[j]; 13 f[i+1] = P[i]==P[j]? j+1 : 0; 14 } 15 } 16 int kmp(int n, int m){ 17 int cnt = 0, j = 0; 18 for(int i=0; i<n; i++){ 19 while(j && P[j]!=T[i]){ 20 j = f[j]; 21 } 22 if(P[j] == T[i]) j++; 23 if(j == m) return i-m+1+1; //cnt++ 24 } 25 return -1; 26 } 27 int main(){ 28 // freopen("in.txt", "r", stdin); 29 int tt; 30 scanf("%d", &tt); 31 while(tt--){ 32 int n, m; 33 scanf("%d%d", &n, &m); 34 for(int i=0; i<n; i++){ 35 scanf("%d", &T[i]); 36 } 37 for(int i=0; i<m; i++){ 38 scanf("%d", &P[i]); 39 } 40 getnext(m); 41 printf("%d\n", kmp(n, m)); 42 } 43 return 0; 44 }
D - Oulipo
这个KMP(计数)太明显了,不说了。
1 #include <cstdio> 2 #include <string> 3 #include <cstring> 4 #include <algorithm> 5 #include <iostream> 6 using namespace std; 7 char p[10010], t[1000010]; 8 int f[10010]; 9 void getnext(){ 10 int m = strlen(p); 11 f[0]=f[1] = 0; 12 for(int i=1; i<m; i++){ 13 int j=f[i]; 14 while(j && p[i]!=p[j]) j=f[j]; 15 f[i+1] = p[i]==p[j]?j+1:0; 16 } 17 } 18 int kmp(){ 19 int n = strlen(t), m =strlen(p); 20 int cnt=0, j=0; 21 for(int i=0; i<n; i++){ 22 while(j && p[j]!=t[i]) j=f[j]; 23 if(p[j]==t[i]) j++; 24 if(j==m) cnt++; 25 } 26 return cnt; 27 } 28 void show() 29 { 30 int m=strlen(p); 31 for(int i=0;i<=m;i++) printf("%4c",p[i]); 32 putchar(‘\n‘); 33 for(int i=0;i<=m;i++) printf("%4d",f[i]); 34 putchar(‘\n‘); 35 } 36 int main(){ 37 // freopen("in.txt", "r", stdin); 38 int tt; 39 scanf("%d", &tt); 40 while(tt--){ 41 scanf("%s", p); 42 getnext(); 43 scanf("%s", t); 44 printf("%d\n", kmp()); 45 } 46 return 0; 47 }
E - Theme Section
题意:
有种音乐,音乐用M(10^6)个小写字母表示,主旋律为E,音乐形如EAEBE,计算主旋律E最长可以多长。
Thinking:
这道题数据应该是有问题的,我的1A解法肯定是错误的。
题目很好理解,看到这个形式熟悉的EAEBE,以及最长,就想当然的以为是求最大的前后缀匹配(感觉自己脑子有点简单),然后就开始讨论情况,按长度分为两种,然后就谜之默认了中间的E不存在,然后胡搞了下,竟然AC了,开始很高兴,后来去厕所回来的过程中想到了这个中间的E如果小于前后缀匹配的最大值怎么办?
然后回来构造了个样例 aacsdafrtaa ,果然程序运行的答案错了。
下面贴出错误code
1 #include <cstdio> 2 #include <iostream> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 using namespace std; 8 const int maxn = 1e6+10; 9 char str[maxn]; 10 int f[maxn]; 11 void getnext(int m){ 12 f[0] = f[1] = 0; 13 for(int i=1; i<m; i++){ 14 int j = f[i]; 15 while(j && str[i]!=str[j]) j=f[j]; 16 f[i+1] = str[i]==str[j]?j+1:0; 17 } 18 } 19 int main(){ 20 // freopen("in.txt", "r", stdin); 21 int n; 22 scanf("%d", &n); 23 while(n--){ 24 scanf("%s", str); 25 int m = strlen(str); 26 if(m<=2){ 27 printf("0\n"); 28 }else{ 29 getnext(m); 30 int tmp = min((int)ceil(m/2.0)-1, f[m]); 31 //cout << "ceil(m/2) = " << ceil(m/2.0) << endl; 32 printf("%d\n", tmp); 33 } 34 } 35 return 0; 36 } 37 /* 38 aacsdafrtaa 39 */
教训是:思考问题不全面,总想以偷懒的方法做题。
下面思考正解,其实相比上面的思考,只差一个要解决的问题就是中间的E:沿着next数组,找到字符串非前缀后缀的中间那段是否出现前缀(后缀),这个过程是一个kmp的过程,只要找到即可退出枚举,因为这是沿着next走,即保证长度由大到小。
1 #include <cstdio> 2 #include <iostream> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 using namespace std; 8 const int maxn = 1e6+10; 9 char str[maxn]; 10 int f[maxn]; 11 bool vis[maxn]; 12 void getnext(int m){ 13 f[0]=-1; 14 for(int i=1, j=-1; i<m; i++){ 15 while(j>=0 && str[i]!=str[j+1]) j=f[j]; 16 if(str[j+1]==str[i]) j++; 17 f[i] = j; 18 } 19 } 20 int kmp(int n, int m){ 21 //n:母串长 从[m-1,n-m] kmp子串 22 for(int i=m-1, j=-1; i<n-m; i++){ 23 while(j>=0 && str[j+1]!=str[i]) j=f[j]; 24 if(str[j+1]==str[i]) j++; 25 if(j+1 == m) return m; 26 } 27 return -1; 28 } 29 int main(){ 30 freopen("in.txt", "r", stdin); 31 int n; 32 scanf("%d", &n); 33 while(n--){ 34 scanf("%s", str); 35 int m = strlen(str); 36 if(m<=2){ 37 printf("0\n"); 38 }else{ 39 getnext(m); 40 /* 41 for(int i=1; i<=m; i++){ 42 cout << f[i] << " "; 43 } 44 cout << endl; 45 */ 46 int j = m-1, tmp=-1; 47 while(f[j] >= 0){ 48 int len = kmp(m, f[j]+1); 49 if(len > tmp){ 50 tmp = len; 51 break; 52 } 53 j = f[j]; 54 } 55 if(tmp==-1) printf("0\n"); 56 else printf("%d\n", tmp); 57 } 58 } 59 return 0; 60 }
F - Cyclic Nacklace
题意:题目废话太多,直接从The charmbracelet is made up with那里开始看。向一个字符串加多少字符可以保证全部字符串至少循环2次。
Thinking:
next数组找到最大前后缀匹配后即得到循环前缀,然后判断是否已经自循环多次,是否只有一个珍珠(字符),这些情况不用加字符;剩下的情况则通过取余操作去掉一个循环节,即得到剩下存在的字符,即可知要加的字符数。
1 #include <cstdio> 2 #include <iostream> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 using namespace std; 8 9 const int maxn = 100005; 10 char str[maxn]; 11 int f[maxn]; 12 13 void getnext(int m){ 14 f[0] = f[1] = 0; 15 for(int i=1; i<m; i++){ 16 int j = f[i]; 17 while(j && str[i]!=str[j]){ 18 j = f[j]; 19 } 20 f[i+1] = str[i]==str[j]?j+1:0; 21 } 22 } 23 int main(){ 24 // freopen("in.txt", "r", stdin); 25 int tt; 26 scanf("%d", &tt); 27 while(tt--){ 28 scanf("%s", str); 29 int m = strlen(str); 30 getnext(m); 31 /* 32 for(int i=1; i<=m; i++){ 33 cout << f[i] << " "; 34 } 35 cout << endl; 36 */ 37 int tmp = m - f[m]; 38 if(m != tmp && m % tmp==0){ 39 printf("0\n"); 40 }else{ 41 printf("%d\n", tmp - f[m]%tmp); 42 } 43 } 44 return 0; 45 }
B - Always an integer
题意:给定一个形如P/D(P:n的整系数多项式,D是正整数)的多项式,判断它是否在所有正整数处取到整数值。
这题没做出来,记录下学习心得:
这里先记一个结论:一个整系数多项式P总是正整数D的倍数的判断依据:把n=1,2,……k+1带入试一遍即可,k是多项式中最高项的次数。
这里证明训练指南124页很详细,数学归纳+查分数列推出。
本题还有难点在于字符串的处理,知道数学结论后,写了好久,怎么都写不对。这里参考了一些博客,找到了一种比较好理解的方法,就是通过结构体保存 系数 和 阶数,然后通过字符‘n’和字符‘/‘将数据分为三类:系数,阶数,除数。得到这些数据后,就利用结论写就好了。
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <map> 5 #include <string> 6 #include <cctype> 7 using namespace std; 8 #define LL long long 9 struct D{ 10 LL x, k; 11 }d[110]; 12 int cnt; 13 LL mu, maxk; 14 /* 15 * 模拟时数字和符号分开处理,符号根据情况也分开处理,可以多用参数标记上回合运算的一些情况,并正确更新参数 16 */ 17 void build(const string &str){ 18 maxk = mu = 0; 19 cnt = 0; 20 LL s=0, a=0, b=0, flag = 1; 21 int len = str.size(); 22 for(int i=0; i<len; i++){ 23 if(str[i]>=‘0‘ && str[i]<=‘9‘){ 24 if(s==0){ // n^符号前的数字 25 a = a*10 + (str[i]-‘0‘); 26 }else if(s==1){ // n^符号后的数字 27 b = b*10 + (str[i]-‘0‘); 28 }else if(s==2){ //除号后的数字 29 mu = mu*10 + (str[i]-‘0‘); 30 } 31 }else if(str[i]==‘/‘){ 32 s = 2; 33 }else if(str[i] == ‘n‘){ 34 s = 1; 35 }else if(str[i]==‘)‘ || str[i]==‘+‘ || str[i]==‘-‘){ 36 if(s >= 1){ 37 if(a==0) a=1; 38 if(b==0) b=1; 39 } 40 maxk=max(maxk, b); //保存最大的阶 41 d[cnt].x = a * flag; // k阶对应的系数 42 d[cnt].k = b; // k阶对应的指数 43 cnt++; 44 if(str[i]==‘-‘){ 45 flag = -1; 46 }else if(str[i]==‘+‘){ 47 flag = 1; 48 } 49 a=b=s=0; 50 } 51 } 52 } 53 LL pow_(LL a, LL b){ 54 LL ans = 1; 55 while(b){ 56 if(b&1){ 57 ans = ans * a % mu; 58 } 59 b >>= 1; 60 a = a * a % mu; 61 } 62 return ans; 63 } 64 bool solve(){ 65 for(LL i=1; i<=maxk+1; i++){ 66 LL ans = 0; 67 for(int j=0; j<cnt; j++){ 68 ans = (ans + d[j].x * pow_(i, d[j].k)) % mu; 69 } 70 if(ans != 0) return false; 71 } 72 return true; 73 } 74 int main(){ 75 // freopen("in.txt", "r", stdin); 76 string s; 77 int tt = 0; 78 while(cin >> s){ 79 //cout << s << endl; 80 if(s == ".")break; 81 build(s); 82 printf("Case %d: %s\n", ++tt, solve()?"Always an integer":"Not always an integer"); 83 } 84 return 0; 85 }
还有很多内容,待补。
标签:== title else 循环 vector string amp build print
原文地址:https://www.cnblogs.com/seaupnice/p/9490775.html