C++模板(2) 一、数论 1、二进制优化最大公因数   二、数据结构 1、二叉查找树   三、动态规划 1、最长公共子串   1、KMP

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 } 
View Code

 

二、数据结构

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 }
View Code

 

三、动态规划

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 } 
View Code

 

四、其它

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 }  
View Code