程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> Fukuoka 2011 F - City Merger <路徑壓縮,位運算,AC自動機>

Fukuoka 2011 F - City Merger <路徑壓縮,位運算,AC自動機>

編輯:C++入門知識

本題求用最短的長度字符串包含所給子串...由於存在多串匹配的問題...容易聯想到AC自動機...
       最多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:
[cpp] 
#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[n]=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[n][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; 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved