ZOJ 3535 Gao the String II

来源:互联网 发布:赛门铁克备份软件代理 编辑:程序博客网 时间:2024/05/01 23:50

搞了半天,预处理各种错。。。

先说下题目意思吧,不好理解,当时比赛的时候是以为把得到的S和每个Bi去比,Bi的每一位如果正确对上了就算得1分,结果样例直接没过,就扔掉了

后来看了解题报告和标程,发现应该是S和每个Bi去比,当Bi是S的子串时才得1分


那么我们可以用自动机来进行DP,首先预处理对于每个Ai,可以和Aj的第几位开始的后缀进行link,然后剩下的自动机DP就比较简单了

定义dp[i][j][k]表示当前长度为i,且在自动机的状态j,并且这个状态是由link Ak转移过来的,我们对于Ak的每个可行的link单词进行枚举,转移即可


代码:

#include<iostream>#include<cstring>#include<cstdio>#include<algorithm>#include<cmath>#include<stack>#include<queue>#include<vector>#include<map>#include<ctime>using namespace std;const int MAX=10000;struct node {int next[26],fail,s;};node trie[MAX];int idx,n,m,L,len[55];char a[55][15];vector<int>adj[55],start[55];int dp[55][555][55];int New(){for(int i=0;i<26;i++)trie[idx].next[i]=-1;trie[idx].s=0;return idx++;}void insert(char str[]){int p=0,i=0,del;while(str[i]){del=str[i]-'a';if(trie[p].next[del]==-1)trie[p].next[del]=New();p=trie[p].next[del];i++;}trie[p].s++;}void build_fail(){queue<int>que;int fa,pre,i;trie[0].fail=-1;for(i=0;i<26;i++){if(trie[0].next[i]!=-1){trie[trie[0].next[i]].fail=0;que.push(trie[0].next[i]);}elsetrie[0].next[i]=0;}while(!que.empty()){fa=que.front();que.pop();trie[fa].s+=trie[trie[fa].fail].s;for(i=0;i<26;i++){pre=trie[fa].fail;while(trie[pre].next[i]==-1)pre=trie[pre].fail;if(trie[fa].next[i]!=-1){trie[trie[fa].next[i]].fail=trie[pre].next[i];que.push(trie[fa].next[i]);}elsetrie[fa].next[i]=trie[pre].next[i];}}}void init(){int i,j,k,l;for(i=0;i<=n;i++){adj[i].clear();start[i].clear();}for(i=1;i<=n;i++){for(j=1;j<=n;j++){for(k=0;k<len[i]&&k<len[j];k++){bool flag=true;for(l=1;l<=k;l++){if(a[i][len[i]-k+l-1]!=a[j][l-1]){flag=false;break;}}if(flag){adj[i].push_back(j);start[i].push_back(k);}}}}for(i=1;i<=n;i++){adj[0].push_back(i);start[0].push_back(0);}}void solve(){int res=0,i,j,k,l;memset(dp,-1,sizeof(dp));dp[0][0][0]=0;for(int ll=0;ll<L;ll++){for(i=0;i<idx;i++){for(j=0;j<=n;j++){if(dp[ll][i][j]==-1)continue;int xx=adj[j].size();for(k=0;k<xx;k++){int del=len[adj[j][k]]-start[j][k];if(ll+del>L)continue;int ns=i;int x=start[j][k],sum=0;for(int y=0;y+x<len[adj[j][k]];y++){int tmp=a[adj[j][k]][x+y]-'a';ns=trie[ns].next[tmp];sum+=trie[ns].s;}l=adj[j][k];if(dp[ll+del][ns][l]<dp[ll][i][j]+sum){dp[ll+del][ns][l]=dp[ll][i][j]+sum;//cout<<ll<<" "<<i<<" "<<j<<" ->"<<ll+del<<" "<<ns<<" "<<l<<" sum="<<sum<<endl;}if(res<dp[ll+del][ns][l])res=dp[ll+del][ns][l];}}}}printf("%d\n",res);}int main(){//freopen("in.txt","r",stdin);//freopen("out2.txt","w",stdout);int i,j,k;//int st=clock();while(scanf("%d%d%d",&n,&m,&L)!=EOF){idx=0;New();for(i=1;i<=n;i++){scanf("%s",a[i]);len[i]=strlen(a[i]);}for(i=1;i<=m;i++){scanf("%s",a[n+1]);insert(a[n+1]);}build_fail();init();solve();//int en=clock();cout<<en-st<<"ms"<<endl;}return 0;}