ZOJ 3430

无力吐槽。。

代码如下:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<vector>
  4 #include<queue>
  5 #include<iostream>
  6 using namespace std;
  7 const int N = 50010;
  8 const int kind = 256;
  9 char file[N],val[N];
 10 int digit[N],code[N],Size,vis[N];
 11 
 12 struct node{
 13         int Next[kind];
 14         int fail;
 15         int count;
 16         void init()
 17         {
 18                 memset(Next,-1,sizeof(Next));
 19                 fail = 0;
 20                 count = 0;
 21         }
 22 
 23 }s[N];
 24 int sind;
 25 int q[N],qin,qout;
 26 void cas_init()
 27 {
 28         s[0].init();
 29         sind=1;
 30 }
 31 
 32 void ins()//向树中插入字母
 33 {
 34     int i, j, ind;
 35     for(i = ind = 0;code[i] >= 0;i++)
 36     {
 37         j = code[i];//求出字母在next中的编号
 38         if(s[ind].Next[j]== -1)//如果不存在子节点j,则构造新的
 39         {
 40             s[sind].init();//初始化
 41             s[ind].Next[j] = sind++;//连向当前结点,并sind++代表总结点数
 42         }
 43         ind = s[ind].Next[j]; //向下走
 44     }
 45     s[ind].count++;//增加离根结点这条路径上字符串的个数,一条路上可能不止一个单词
 46 }
 47  void make_fail()//构造失配指针
 48  {
 49      qin = qout = 0;//初始化队列
 50      int i,ind,ind_f;
 51      for(i=0;i<kind;i++)
 52      {
 53          if(s[0].Next[i]!=-1)
 54              q[qin++]=s[0].Next[i];//先考虑根结点,和根结点相连的都入队
 55      }
 56        while(qin!=qout)
 57        {
 58                 ind = q[qout++];//记录队首结点
 59                 for(i = 0;i < kind; i++)//遍历队首结点的Next
 60                 {
 61                      //   cout<<qin<<" "<<qout<<endl;
 62                     if(s[ind].Next[i]!=-1)//如果结点Next不为空
 63                     {
 64                         q[qin++] = s[ind].Next[i];//将儿子节点入队
 65                         ind_f = s[ind].fail;//记录节点的失配指针指向
 66                         while(ind_f>0 && s[ind_f].Next[i]==-1)
 67                         /*当失配指针不为root时,一直循环直到找到一个结点是儿子是i值或者到了root*/
 68                             ind_f = s[ind_f].fail;
 69                         if(s[ind_f].Next[i]!=-1) //如果当前结点有儿子的话记录下来备用
 70                             ind_f = s[ind_f].Next[i];
 71                         s[s[ind].Next[i]].fail = ind_f; //使当前结点的失配指针指向刚才记录的结点完成失配指针的寻找构造
 72                     }
 73                 }
 74        }
 75  }
 76 int fd()
 77  {
 78        memset(vis,0,sizeof(vis));
 79      int ct = 0; //记录“单词的个数”
 80      int di,i,ind ,p; //di为指向“文章”的指针,ind为指向失配结点的指针(即trie树中失配的指针)
 81      for(di = ind =0; code[di]>=0; di++)
 82      {
 83          i = code[di];
 84          while(ind>0 && s[ind].Next[i] == -1)
 85      /*当ind指针不是root和找不到结点的儿子是i时一直找下去(类似于KMP中while循环)*/
 86              ind = s[ind].fail; //一直寻找失配指针
 87 
 88          if(s[ind].Next[i]!= -1)//找到了合适的失配指针
 89          {
 90              ind = s[ind].Next[i]; //指向这个儿子的节点,更新ind的值进行下一次匹配
 91 
 92              p = ind; //用p来临时代替ind
 93              while(p>0 && !vis[p])
 94              /* p>0 表示还没到root,count!=-1表示指针前还有单词*/
 95             {
 96                  ct+=s[p].count;//加上有的单词的个数
 97                  vis[p]=1;
 98                  //不重复计算,注意这里很重要
 99                  p = s[p].fail;//一直寻找失配指针
100              }
101          }
102      }
103      return ct;//返回单词个数
104  }
105 int fun(char ch)  //convert char to int
106 {
107     if(ch >= 'A' && ch <= 'Z') return ch - 'A';
108     if(ch >= 'a' && ch <= 'z') return ch - 'a' + 26;
109     if(ch >= '0' && ch <= '9') return ch - '0' + 52;
110     if(ch == '+') return 62;
111     return 63;
112 }
113 
114 void change(char *str)
115 {
116     int i, j, len, t;
117     vector<int> v;
118     memset(digit, 0, sizeof(digit));
119     for(len = strlen(str); str[len-1] == '='; len--) ;
120     str[len] = '\0';
121     for(i = 0; i < len; i++)
122         v.push_back(fun(str[i]));
123     for(i = 0; i < v.size(); i++) {
124         for(j = 6 * (i + 1) - 1; j >= 6 * i; j--) {
125             if(v[i]&1)
126                 digit[j] = 1;
127             v[i] >>= 1;
128         }
129     }
130     int k = v.size() * 6 / 8; //the number of letter before encode
131     for(i = 0; i < k; i++) {
132         for(t = 0, j = 8 * i; j < 8 * (i + 1); j++)
133             t = (t << 1) + digit[j];
134         code[i] = t;
135     }
136     code[i] = -1;
137 }
138 
139 int main()
140 {
141     ios::sync_with_stdio(false);
142     int n,m;
143     while(cin>>n)
144     {
145           //  memset(s,0,sizeof(s));
146         cas_init();
147         for(int i = 0;i < n;i ++)
148         {
149                 cin>>val;
150                 change(val);
151                 ins();
152         }
153         make_fail();
154         cin>>m;
155         while(m--)
156         {
157                 cin>>file;
158                 memset(code,0,sizeof(code));
159                 change(file);
160                 cout<<fd()<<endl;
161         }
162         cout<<endl;
163     }
164 }
View Code

 

posted on 2015-09-06 12:38  小松song  阅读(119)  评论(0)    收藏  举报

导航