ZOJ-3430 AC自动机+恶心...

      这道题要留意的是转换后的字符,是0~255的..包括一些转义字符..譬如'\0'的..so..用字符串存会很囧..所以用int数组存...

      本题分为两步...第一步是翻译字符串...第二步是AC自动机...

      我对位运算很不熟练...所以在翻译字符串用的是最原始最原始的方法...先将字符串读入..转化为二进制串..再翻译成所需的...还好...虽然效率不高..但也没耽误太多时间..

      第二步就是AC自动机模板题了...有好几个月没写AC自动机...发现自己写出来的和以前完全不同了...但感觉现在写的这个更为有效率,代码量也更小..本来就没必要递归来递归去的...

      题目给了一段转化数据的代码段(是从输出的形式转化为输入的形式..)..虽然不能应用到程序里...但可以充分利用这个代码段来生成数据,检验自己的程序~~

      我发现的问题就是...当前到达字典数的某个点..不仅要看这个点是否是病毒标记点..而且其fail不断上去有哪些是病毒标记点都要查询...我就因为这个WA了好久....后来想起利用题目中的代码段生成数据...立马找到错误了...

      顺便提供一组数据吧:

Data:

7
YQ== 
Yg==
YWI=
YWJj
YWJjZA==
YmNk
Y2Q=
1
YWJjZA==


Ans:

7


Program:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
struct node
{
      int virus,son[256],fail;   
}point[50000];
int n,m,ans,h,turn[256],l,temp[80000];
char ss[10000];
int s[10000];
queue<int> myqueue;
bool used[600];
void change()
{
      int i,len,k,j,p; 
      len=strlen(ss);
      l=0;
      for (i=0;i<len;i++)
      if (ss[i]=='=') break;
      else
      {
             k=turn[ss[i]];
             p=32;
             for (j=1;j<=6;j++) 
             {
                   temp[++l]=k/p;
                   k=k%p;  p/=2;
             }
      }
      for (;i<len;i++) l-=2;
      for (i=1;i<=l-7;i+=8)
      {
             k=0;
             for (j=0;j<=7;j++)
                 k=k*2+temp[i+j];  
             s[i/8]=k;
      }
      l/=8;
}
int main()
{
      freopen("input.txt","r",stdin);
      freopen("output.txt","w",stdout);
      int i,k;
      for (i=0;i<=256;i++)
      {
             if (i>='A' && i<='Z') turn[i]=i-'A';
             else
             if (i>='a' && i<='z') turn[i]=i-'a'+26;
             else
             if (i>='0' && i<='9') turn[i]=i-'0'+52;
             else if (i=='+') turn[i]=62; else turn[i]=63;
      }
      while (~scanf("%d",&n))
      {  
             m=0;  
             point[0].virus=point[0].fail=0;
             memset(point[0].son,0,sizeof(point[0].son));
             while (n--)
             {
                   scanf("%s",ss);
                   change();
                   k=0;
                   for (i=0;i<l;i++)
                   if (!point[k].son[s[i]])
                   {
                          m++;
                          point[k].son[s[i]]=m;
                          point[m].virus=point[m].fail=0;
                          memset(point[m].son,0,sizeof(point[m].son));
                          k=m;
                   }else k=point[k].son[s[i]];
                   point[k].virus=n+1;
             }
             while (!myqueue.empty()) myqueue.pop();
             for (i=0;i<256;i++)
                if (point[0].son[i])
                   myqueue.push(point[0].son[i]); 
             while (!myqueue.empty())
             {
                   h=myqueue.front();
                   myqueue.pop();
                   for (i=0;i<256;i++)
                   if (point[h].son[i])
                   {
                          myqueue.push(point[h].son[i]);
                          k=point[h].fail;
                          while (k && !point[k].son[i]) k=point[k].fail;
                          if (point[k].son[i]) 
                              point[point[h].son[i]].fail=point[k].son[i];
                   }                   
             }
             scanf("%d",&n); 
             while (n--)
             {
                   scanf("%s",ss);
                   change();
                   memset(used,false,sizeof(used));
                   used[0]=true;
                   ans=0;
                   k=0;
                   for (i=0;i<l;i++)
                   {
                         while (k && !point[k].son[s[i]]) k=point[k].fail;
                         if (point[k].son[s[i]]) k=point[k].son[s[i]]; 
                         h=k;
                         while (h)
                         {
                              if (!used[point[h].virus])
                              {                 
                                    ans++;
                                    used[point[h].virus]=true;
                              }
                              h=point[h].fail;
                         }                         
                   }   
                   printf("%d\n",ans);                
             }
             printf("\n");
      } 
      return 0;
}


你可能感兴趣的:(ZOJ-3430 AC自动机+恶心...)