zoukankan      html  css  js  c++  java
  • POJ3007Organize Your Train part II

    转载请注明出处:優YoU  http://user.qzone.qq.com/289065406/blog/1307515870

     

    大致题意:

    给定一个字符串,从任意位置把它切为两半,得到两条子串

    定义 子串1s1,子串2s2,子串1的反串为s3,子串2的反串为s4

    现在从s1 s2 s3 s4中任意取出两个串组合,问有多少种不同的组合方法

     

    规定:

    (1)       Si不能和其 反串 组合

    (2)       Si+Sj Sj+Si 是两种组合方式(但未必是不同的组合方式)

     

    解题思路:

    利用hash表查重

     

    穷举全部组合的情况,每枚举一个就记录一次,假如后面枚举的组合已经存在记录,说明组合重复,计数器不变,否则计数器+1

     

    本题不能用STLmap映射,map太慢会超时

    自己写Hash表吧!

    对于*ps指向的字符串s,我定义的关键字 

     

    可以认为i为权重,利用字母的ASCII得到key

    解决冲突方法为链地址法

     

      1 //Memory Time 
    2 //2380K 157MS
    3
    4 #include<iostream>
    5 using namespace std;
    6
    7 const int size=80;
    8 const int mod=99991;
    9 int count; //计数器
    10
    11 typedef struct HASH
    12 {
    13 char s[size];
    14 struct HASH* next;
    15 HASH()
    16 {
    17 next=0; //0<=>NULL
    18 }
    19 }Hashtable;
    20
    21 Hashtable* Hash[mod]; //hash[]是指针数组,存放地址
    22
    23 void hash(char* s);
    24 void StrCopy(char* s1,char* s2); //把s2复制到s1,要确保s1.len>s2.len
    25 void StrCut(char* s,char* s1,char* s2,int k,int slen); //把s前k个字符(0~k-1)复制到s1,第k到slen的字符复制到s2
    26 void StrInvert(char* s1,char* s2,int len); //把s1逆序存放到s2
    27 char* StrCat(char* s1,char* s2,char* str); //把s2连接到s1后,存放到s
    28
    29 int main(void)
    30 {
    31 int n;
    32 cin>>n;
    33 while(n--)
    34 {
    35 char train[size];
    36 cin>>train;
    37 int len=strlen(train);
    38 if(len==1)
    39 {
    40 cout<<1<<endl;
    41 continue;
    42 }
    43
    44 memset(Hash,0,sizeof(Hash)); //0 <-> NULL
    45 count=0;
    46
    47 for(int i=1;i<=len-1;i++) //i为火车分开的两部分中,前一部分的节数
    48 {
    49 char s1[size],s2[size];
    50 char s3[size],s4[size]; //s3为s1的逆序,s4为s2的逆序
    51 char str[size];
    52
    53 StrCut(train,s1,s2,i,len);
    54 StrInvert(s1,s3,i);
    55 StrInvert(s2,s4,len-i);
    56
    57 /*标记组合方式*/
    58
    59 hash(train); //s1与s2组合就是原来的train
    60 StrCat(s2,s1,str);
    61 hash(str);
    62 StrCat(s1,s4,str);
    63 hash(str);
    64 StrCat(s4,s1,str);
    65 hash(str);
    66 StrCat(s3,s2,str);
    67 hash(str);
    68 StrCat(s2,s3,str);
    69 hash(str);
    70 StrCat(s3,s4,str);
    71 hash(str);
    72 StrCat(s4,s3,str);
    73 hash(str);
    74 }
    75
    76 cout<<count<<endl;
    77 }
    78 return 0;
    79 }
    80
    81
    82 void hash(char* s)
    83 {
    84 char* ps=s;
    85
    86 int key=0;
    87 for(int i=1;*ps;i++)
    88 key+=*(ps++)*i;
    89 key%=mod;
    90
    91 if(!Hash[key]) //新key
    92 {
    93 Hashtable* pn=new Hashtable; //由于要存放数据,必须申请空间
    94 //Hashtable* pn;只是单纯申请一个地址空间
    95 StrCopy(pn->s,s);
    96 Hash[key]=pn;
    97
    98 count++;
    99 }
    100 else //key值冲突
    101 {
    102 Hashtable* pn=Hash[key]; //pn指向冲突位置的链表开头
    103
    104 if(!strcmp(pn->s,s))
    105 return; //不计数返回
    106 else
    107 {
    108 while(pn->next)
    109 {
    110 if(!strcmp(pn->next->s,s)) //地址冲突且字符串相同
    111 return;
    112
    113 pn=pn->next;
    114 }
    115
    116 //地址冲突但字符串不同
    117
    118 Hashtable* temp=new Hashtable;
    119 StrCopy(temp->s,s);
    120 pn->next=temp; //记录新字符串
    121
    122 count++;
    123 }
    124 }
    125 return;
    126 }
    127
    128 void StrCopy(char* s1,char* s2) //把s2复制到s1
    129 {
    130 char* ps1=s1;
    131 char* ps2=s2;
    132 while(*ps2)
    133 *(ps1++)=*(ps2++);
    134 *ps1='\0';
    135
    136 return;
    137 }
    138
    139 void StrCut(char* s,char* s1,char* s2,int k,int slen) //把s前k个字符(0~k-1)复制到s1,第k到slen的字符复制到s2
    140 {
    141 int i,ps1=0,ps2=0;
    142
    143 for(i=0;i<k;i++)
    144 s1[ps1++]=s[i];
    145 s1[ps1]='\0';
    146
    147 for(;i<slen;i++)
    148 s2[ps2++]=s[i];
    149 s2[ps2]='\0';
    150
    151 return;
    152 }
    153
    154 void StrInvert(char* s1,char* s2,int len) //把s1逆序存放到s2
    155 {
    156 int ps=0;
    157 s2[len]='\0';
    158 for(int i=len-1;i>=0;i--)
    159 s2[i]=s1[ps++];
    160
    161 return;
    162 }
    163
    164 char* StrCat(char* s1,char* s2,char* str) //把s2连接到s1后,存放到s
    165 {
    166 int i,ps=0;
    167 for(i=0;s1[i]!='\0';i++)
    168 str[ps++]=s1[i];
    169 for(i=0;s2[i]!='\0';i++)
    170 str[ps++]=s2[i];
    171 str[ps]='\0';
    172
    173 return str;
    174 }
    [ EXP技术分享博客 ] 版权所有,转载请注明出处: http://exp-blog.com
  • 相关阅读:
    Centos warning: setlocale: LC_CTYPE: cannot change locale (UTF-8): No such file or directory
    gitlab安装与配置(Centos6.8)
    重装MAC系统 “安装器有效负载签名检查失败” 解决方法
    nginx配置限制同一个ip的访问频率
    nginx配置文件详解
    C# 获取打印机列表以及串口
    JQ将数组转换为Json
    快速查看SQL Server 中各表的数据量以及占用空间大小
    键盘unicode值对照表
    JavaScript经典代码【二】【javascript判断用户点了鼠标左键还是右键】
  • 原文地址:https://www.cnblogs.com/lyy289065406/p/2122846.html
Copyright © 2011-2022 走看看