您的位置:首页 > 其它

hdu 4534 郑厂长系列故事——新闻净化

2013-04-04 12:57 330 查看
http://acm.hdu.edu.cn/showproblem.php?pid=4534

自动机+DP(状态压缩)

整体思路应该很明确,但要注意一些细节方面的处理 否则会wa

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<map>
#include<set>
#include<vector>
#include<stack>
#include<queue>

using namespace std;
const int MOD=1000000007;
const int N=110;
const int M=1610;
const int K=26;
struct nodeTrie
{
int v;
int k;
int fail;
int next[K];
void initialize()
{
v=0;
k=0;
fail=-1;
memset(next,-1,sizeof(next));
}
}trie[M];
int cnt,root;
int to[M][K];
char s[K];
char words
;
int dp1[2][M][1<<8],dp2[2][M][1<<8];
int getNewNode()
{
++cnt;
trie[cnt].initialize();
return cnt;
}
void addWord(int p,char *s,int k,int l)
{
if(s[0]=='\0') return ;
for(int i=0;s[i]!='\0';++i)
{
if(trie[p].next[s[i]-'a']==-1)
trie[p].next[s[i]-'a']=getNewNode();
p=trie[p].next[s[i]-'a'];
}
if(k==999)
trie[p].k=(1<<(l-1));
else if(k==-999)
trie[p].k=-1;
else
trie[p].v=k;
}
int init(int n)
{
cnt=-1;
root=getNewNode();
int l=0;
while(n--)
{
int k;
scanf("%s %d",s,&k);//puts(s);cout<<k<<endl;
if(k==999) ++l;
addWord(root,s,k,l);
}
return l;
}
void bfs(int p)
{
trie[p].fail=root;
queue<int>qt;
qt.push(p);
while(!qt.empty())
{
int y;
int x=qt.front();qt.pop();
for(int i=0;i<K;++i)
if(trie[x].next[i]!=-1)
{
qt.push(trie[x].next[i]);
if(x==root)
{trie[trie[x].next[i]].fail=root;continue;}
y=trie[x].fail;
while(y!=root&&trie[y].next[i]==-1)
y=trie[y].fail;
if(trie[y].next[i]!=-1)
trie[trie[x].next[i]].fail=trie[y].next[i];
else
trie[trie[x].next[i]].fail=root;
int l=trie[x].next[i],r=trie[trie[x].next[i]].fail;
if(trie[l].k==-1||trie[r].k==-1)
trie[l].k=-1;
else {trie[l].k=(trie[l].k|trie[r].k);trie[l].v+=trie[r].v;}
}
}
}
void makeTo(int n,int k)
{
for(int i=0;i<=n;++i)
for(int j=0;j<k;++j)
{

int p=i;
while(p!=root&&trie[p].next[j]==-1)
p=trie[p].fail;
if(trie[p].next[j]!=-1)
to[i][j]=trie[p].next[j];
else
to[i][j]=root;
}
};
int main()
{
//freopen("data.in","r",stdin);
int T;
scanf("%d",&T);
for(int w=1;w<=T;++w)
{
int n;
scanf("%d",&n);
int h=(1<<init(n));
bfs(root);
makeTo(cnt,K);
scanf("%s",words);
int m=strlen(words);
memset(dp1,0,sizeof(dp1));
memset(dp2,0,sizeof(dp2));
int M=0,P=0;
for(int i=0;i<=m;++i)
{
for(int j=0;j<=cnt;++j)
for(int l=0;l<h;++l)
{dp1[(i+1)%2][j][l]=0;dp2[(i+1)%2][j][l]=0;}
for(int j=0;j<=cnt;++j)
for(int l=0;l<h;++l)
{
if(dp1[i%2][j][l]==0&&(j>0||l>0)) continue;
if(l==(h-1))
{
if(M<dp1[i%2][j][l]||(M==dp1[i%2][j][l]&&P<dp2[i%2][j][l]))
{M=dp1[i%2][j][l];P=dp2[i%2][j][l];}
}
if(i==m) continue;
int r=to[j][words[i]-'a'];
if(dp1[(i+1)%2][j][l]<dp1[i%2][j][l]||
(dp1[(i+1)%2][j][l]==dp1[i%2][j][l]&&dp2[(i+1)%2][j][l]<dp2[i%2][j][l]))
{dp1[(i+1)%2][j][l]=dp1[i%2][j][l];dp2[(i+1)%2][j][l]=dp2[i%2][j][l];}
if(trie[r].k!=-1)
{
int k=(l|(trie[r].k));
if(dp1[(i+1)%2][r][k]<dp1[i%2][j][l]+1||
(dp1[(i+1)%2][r][k]==dp1[i%2][j][l]+1&&dp2[(i+1)%2][r][k]<dp2[i%2][j][l]+trie[r].v))
{dp1[(i+1)%2][r][k]=dp1[i%2][j][l]+1;dp2[(i+1)%2][r][k]=dp2[i%2][j][l]+trie[r].v;}
}
}
}
printf("Case %d: ",w);
if(M==0)
printf("Banned\n");
else
printf("%d %d\n",m-M,P);
}
return 0;
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: