您的位置:首页 > 其它

Fukuoka 2011 F - City Merger <路径压缩,位运算,AC自动机>

2012-09-04 16:10 429 查看
本题求用最短的长度字符串包含所给子串...由于存在多串匹配的问题...容易联想到AC自动机...

以前做过的一道类似的题 /article/2097199.html

最多14个city..用14位的二进制数表示已经在串中否...对多串构造Trie树..进一步构造好AC自动机...可以用dp [ k ] [ i ] [ x ] 来表示长度为k的串..末字符落在trie树的i处..包含14个关系的x...但这样的复杂度..以最坏的考虑..会有240*240*16384=943718400=9*10^8...无法接受...

那么此时就要压缩路径了..由于Trie树中有很多无法产生更新的点...没必要dp时一次又一次的路过...所以将Trie树中x非0的点找出来...从每个点开始BFS...做出到其他有效点的最短距离...这样大大优化了dp过程...

Program:

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<stack>
#include<math.h>
#include<map>
#define oo 1000000000
using namespace std;  
struct node
{
    int fail,son[26],city,w;
}point[1001]; 
struct node2
{
    int len,x;
};
int n,m,k,g,arc[303][303],need[303],l[303],dp[2][303][18000];
char s[30]; 
queue<int> myqueue;
void Built_Trie()
{
       int len,i,j,k,h,x;
       memset(point,0,sizeof(point));
       m=0; g=1;
       for (k=0;k<n;k++)
       {
             scanf("%s",s);
             len=strlen(s);
             h=0;
             for (i=0;i<len;i++)
             {
                    x=s[i]-'A';
                    if (!point[h].son[x]) point[h].son[x]=++m;
                    h=point[h].son[x];   
             }
             point[h].w|=g; 
             g*=2;
       }
       g--;
       return;
}
void Built_AC_Automation()
{
       int i,h,k;
       while (!myqueue.empty()) myqueue.pop();
       for (i=0;i<26;i++)
          if (point[0].son[i]) myqueue.push(point[0].son[i]); 
       while (!myqueue.empty())
       {
               h=myqueue.front();
               myqueue.pop();
               point[h].w|=point[point[h].fail].w;
               for (i=0;i<26;i++)
               {
                     k=point[h].fail;
                     while (!point[k].son[i] && k) k=point[k].fail; 
                     point[point[h].son[i]].fail=point[k].son[i];  
                     if (!point[h].son[i]) 
                          point[h].son[i]=point[k].son[i];
                      else
                          myqueue.push(point[h].son[i]);
               }                   
       }
       return;       
}
void Built_Arc()
{
       int i,k,h,len[303];
       memset(arc,-1,sizeof(arc)); 
       n=0;
       for (k=0;k<=m;k++)
          if (point[k].w) 
          {
                need[n++]=k; 
                point[k].city=n;
          }
       need
=0;
       for (k=0;k<=n;k++)
       {
              h=need[k];
              memset(len,-1,sizeof(len));
              myqueue.push(h);
              len[h]=0;
              while (!myqueue.empty())
              {
                    h=myqueue.front();
                    myqueue.pop();
                    i=h;
                    do
                    {
                        if (point[h].w && arc[k][point[h].city-1]==-1)
                           arc[k][point[h].city-1]=len[h];
                        i=point[i].fail;
                    }while (i);
                    for (i=0;i<26;i++)
                      if (len[point[h].son[i]]==-1)
                      {
                            len[point[h].son[i]]=len[h]+1;
                            myqueue.push(point[h].son[i]); 
                      }
              } 
       }     
       for (i=0;i<n;i++) l[i]=arc
[i];
       return ;
}
int EXE_DP()
{
    int p,i,j,t,k,x,ans;
    memset(dp,-1,sizeof(dp)); 
    k=0;
    for (i=0;i<n;i++) dp[k][i][point[need[i]].w]=l[i];
    for (t=1;t<=n;t++)
    {
          k=1-k;
          memset(dp[k],-1,sizeof(dp[k])); 
          for (i=0;i<n;i++)
             for (j=0;j<n;j++) 
                for (p=0;p<=g;p++)
                if (dp[1-k][j][p]!=-1)
                {
                       x=point[need[i]].w|p;
                       if (dp[k][i][x]==-1 || dp[k][i][x]>dp[1-k][j][p]+arc[j][i])
                          dp[k][i][x]=dp[1-k][j][p]+arc[j][i];
                }
    }
    ans=oo;
    for (i=0;i<n;i++)
       if (dp[k][i][g]!=-1 && dp[k][i][g]<ans) ans=dp[k][i][g];
    return ans;
}
int main()
{ 
    while (~scanf("%d",&n))
    {
            if (!n) break;
            Built_Trie();
            Built_AC_Automation();
            Built_Arc(); 
            printf("%d\n",EXE_DP());
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: