一、数论
1、二进制优化最大公因数
1 /* 2 若x=y,则GCD(x,y)=x,否则 3 (1)若x,y均为偶数,则 GCD(x,y)=2*GCD(x/2,y/2); 4 (2)若x为偶数,y为奇数,则 GCD(x,y)=GCD(x/2,y); 5 (3)若x为奇数,y为偶数,则 GCD(x,y)=GCD(x,y/2); 6 (4)若x,y均为奇数,则 GCD(x,y)=GCD(x-y,y) 7 */ 8 inline int gcd(int x,int y) 9 { 10 int i,j; 11 if (x==0) return y; 12 if (y==0) return x; 13 for (i=0;0==(x&1);i++) x>>=1; // 去掉所有的 2 14 for (j=0;0==(y&1);j++) y>>=1; // 去掉所有的 2 15 if (j<i) i=j; // 去掉最大公因数 16 while (1) 17 { 18 if (x<y) x^=y,y^=x,x^=y; 19 if (0==(x-=y)) return y<<i; 20 // 若x==y,gcd==x==y,把以前的次幂乘上去,辗转减 21 while (0==(x&1)) x>>=1; // 去掉所有的 2 22 } 23 }
二、数据结构
1、二叉查找树
1 #include <cstdio> 2 int a[10005]; 3 struct tree{ 4 int fa,ls,rs,key; 5 }b[10005]; 6 int n,num=1; 7 bool add(int id,int v) // 插入 8 { 9 int l=b[id].ls,r=b[id].rs; 10 if (b[id].key==v) return 0; // 要插入的关键字已存在,插入失败 11 if (v<b[id].key) 12 { 13 if (l) add(l,v); 14 else 15 { 16 b[++num].key=v; 17 b[id].ls=num; 18 b[num].ls=b[num].rs=0; 19 b[num].fa=id; 20 } 21 return 1; // 要插入的关键字不存在,插入成功 22 } 23 else // v>b[id].key 24 { 25 if (r) add(r,v); 26 else 27 { 28 b[++num].key=v; 29 b[id].rs=num; 30 b[num].ls=b[num].rs=0; 31 b[num].fa=id; 32 } 33 return 1; // 要插入的关键字不存在,插入成功 34 } 35 } 36 bool del(int id,int v) 37 { 38 int l=b[id].ls,r=b[id].rs; 39 if (b[id].key==v) 40 { 41 int f=b[id].fa; 42 if (!b[id].ls) 43 { 44 if (!b[id].rs) // 该节点没有孩子 45 { 46 if (v<b[f].key) b[f].ls=0; 47 else b[f].rs=0; 48 return 1; 49 } 50 else // 只有右孩子 51 { 52 if (v<b[f].key) b[f].ls=r; 53 else b[f].rs=r; 54 return 1; 55 } 56 } 57 else 58 { 59 if (!b[id].rs) // 只有左孩子 60 { 61 if (v<b[f].key) b[f].ls=l; 62 else b[f].rs=l; 63 return 1; 64 } 65 else // 有两个孩子 66 { 67 if (v<b[f].key) b[f].ls=l; 68 else b[f].rs=l; 69 int x; 70 for (x=l;b[x].rs;x=b[x].rs); 71 b[x].rs=r; 72 return 1; 73 } 74 } 75 } 76 if (v<b[id].key) return l?del(l,v):0; 77 return r?del(r,v):0; // v>b[id].key 78 } 79 void dfs(int id) // 中序遍历 80 { 81 if (b[id].ls) dfs(b[id].ls); 82 printf("%d ",b[id].key); 83 if (b[id].rs) dfs(b[id].rs); 84 return; 85 } 86 int main() 87 { 88 int i,j,x; 89 scanf("%d",&n); 90 scanf("%d",&a[1]); 91 b[1].key=a[1]; 92 b[1].ls=b[1].rs=0; 93 for (i=2;i<=n;i++) 94 scanf("%d",&a[i]), 95 add(1,a[i]); 96 scanf("%d",&x); 97 dfs(1); 98 printf(" "); 99 del(1,x); 100 dfs(1); 101 return 0; 102 }
三、动态规划
1、最长公共子串
1 #include <cstring> 2 #include <cstdio> 3 int T,len1,len2,f[25][25],s; 4 char s1[25],s2[25]; 5 int main() 6 { 7 int i,j; 8 scanf("%d",&T); 9 while (T--) 10 { 11 scanf("%s%s",s1+1,s2+1); 12 len1=strlen(s1+1); 13 len2=strlen(s2+1); 14 memset(f,0,sizeof(f)); 15 s=0; 16 for (i=1;i<=len1;i++) 17 for (j=1;j<=len2;j++) 18 { 19 f[i][j]=(s1[i]==s2[j]?f[i-1][j-1]+1:0); 20 if (f[i][j]>s) s=f[i][j]; 21 } 22 printf("%d ",len1+len2-s*2); 23 } 24 return 0; 25 }
四、其它
1、KMP
1 int KmpSearch(char* s, char* p) 2 { 3 int i = 0; 4 int j = 0; 5 int sLen = strlen(s); 6 int pLen = strlen(p); 7 while (i < sLen && j < pLen) 8 { 9 //①如果j = -1,或者当前字符匹配成功(即S[i] == P[j]),都令i++,j++ 10 if (j == -1 || s[i] == p[j]) 11 { 12 i++; 13 j++; 14 } 15 else 16 { 17 //②如果j != -1,且当前字符匹配失败(即S[i] != P[j]),则令 i 不变,j = next[j] 18 //next[j]即为j所对应的next值 19 j = next[j]; 20 } 21 } 22 if (j == pLen) 23 return i - j; 24 else 25 return -1; 26 } 27 28 29 void GetNext(char* p,int next[]) 30 { 31 int pLen = strlen(p); 32 next[0] = -1; 33 int k = -1; 34 int j = 0; 35 while (j < pLen - 1) 36 { 37 //p[k]表示前缀,p[j]表示后缀 38 if (k == -1 || p[j] == p[k]) 39 { 40 ++k; 41 ++j; 42 next[j] = k; 43 } 44 else 45 { 46 k = next[k]; 47 } 48 } 49 }